?? t42parse.c
字號:
/***************************************************************************//* *//* t42parse.c *//* *//* Type 42 font parser (body). *//* *//* Copyright 2002, 2003, 2004, 2005, 2006 by Roberto Alameda. *//* *//* This file is part of the FreeType project, and may only be used, *//* modified, and distributed under the terms of the FreeType project *//* license, LICENSE.TXT. By continuing to use, modify, or distribute *//* this file you indicate that you have read the license and *//* understand and accept it fully. *//* *//***************************************************************************/#include "t42parse.h"#include "t42error.h"#include FT_INTERNAL_DEBUG_H#include FT_INTERNAL_STREAM_H#include FT_LIST_H#include FT_INTERNAL_POSTSCRIPT_AUX_H /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ /* messages during execution. */ /* */#undef FT_COMPONENT#define FT_COMPONENT trace_t42 static void t42_parse_font_matrix( T42_Face face, T42_Loader loader ); static void t42_parse_encoding( T42_Face face, T42_Loader loader ); static void t42_parse_charstrings( T42_Face face, T42_Loader loader ); static void t42_parse_sfnts( T42_Face face, T42_Loader loader ); static const T1_FieldRec t42_keywords[] = {#undef FT_STRUCTURE#define FT_STRUCTURE T1_FontInfo#undef T1CODE#define T1CODE T1_FIELD_LOCATION_FONT_INFO T1_FIELD_STRING( "version", version ) T1_FIELD_STRING( "Notice", notice ) T1_FIELD_STRING( "FullName", full_name ) T1_FIELD_STRING( "FamilyName", family_name ) T1_FIELD_STRING( "Weight", weight ) T1_FIELD_NUM ( "ItalicAngle", italic_angle ) T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch ) T1_FIELD_NUM ( "UnderlinePosition", underline_position ) T1_FIELD_NUM ( "UnderlineThickness", underline_thickness )#undef FT_STRUCTURE#define FT_STRUCTURE T1_FontRec#undef T1CODE#define T1CODE T1_FIELD_LOCATION_FONT_DICT T1_FIELD_KEY ( "FontName", font_name ) T1_FIELD_NUM ( "PaintType", paint_type ) T1_FIELD_NUM ( "FontType", font_type ) T1_FIELD_FIXED( "StrokeWidth", stroke_width )#undef FT_STRUCTURE#define FT_STRUCTURE FT_BBox#undef T1CODE#define T1CODE T1_FIELD_LOCATION_BBOX T1_FIELD_BBOX("FontBBox", xMin ) T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix ) T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding ) T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings ) T1_FIELD_CALLBACK( "sfnts", t42_parse_sfnts ) { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 } };#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )#define T1_Done_Table( p ) \ do \ { \ if ( (p)->funcs.done ) \ (p)->funcs.done( p ); \ } while ( 0 )#define T1_Release_Table( p ) \ do \ { \ if ( (p)->funcs.release ) \ (p)->funcs.release( p ); \ } while ( 0 )#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root )#define T1_ToInt( p ) \ (p)->root.funcs.to_int( &(p)->root )#define T1_ToBytes( p, b, m, n, d ) \ (p)->root.funcs.to_bytes( &(p)->root, b, m, n, d )#define T1_ToFixedArray( p, m, f, t ) \ (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )#define T1_ToToken( p, t ) \ (p)->root.funcs.to_token( &(p)->root, t )#define T1_Load_Field( p, f, o, m, pf ) \ (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )#define T1_Load_Field_Table( p, f, o, m, pf ) \ (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf ) /********************* Parsing Functions ******************/ FT_LOCAL_DEF( FT_Error ) t42_parser_init( T42_Parser parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux ) { FT_Error error = T42_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 = T42_Err_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; } FT_LOCAL_DEF( void ) t42_parser_done( T42_Parser parser ) { FT_Memory memory = parser->root.memory; /* free the base dictionary only when we have a disk stream */ if ( !parser->in_memory ) FT_FREE( parser->base_dict ); parser->root.funcs.done( &parser->root ); } static int t42_is_space( FT_Byte c ) { return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' || c == '\0' ); } static void t42_parse_font_matrix( T42_Face face, T42_Loader loader ) { T42_Parser parser = &loader->parser; FT_Matrix* matrix = &face->type1.font_matrix; FT_Vector* offset = &face->type1.font_offset; FT_Face root = (FT_Face)&face->root; FT_Fixed temp[6]; FT_Fixed temp_scale; (void)T1_ToFixedArray( parser, 6, temp, 3 ); temp_scale = FT_ABS( temp[3] ); /* Set Units per EM based on FontMatrix values. We set the value to */ /* 1000 / temp_scale, because temp_scale was already multiplied by */ /* 1000 (in t1_tofixed, from psobjs.c). */ root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L, temp_scale ) >> 16 ); /* we need to scale the values by 1.0/temp_scale */ if ( temp_scale != 0x10000L ) { temp[0] = FT_DivFix( temp[0], temp_scale ); temp[1] = FT_DivFix( temp[1], temp_scale ); temp[2] = FT_DivFix( temp[2], temp_scale ); temp[4] = FT_DivFix( temp[4], temp_scale ); temp[5] = FT_DivFix( temp[5], temp_scale ); temp[3] = 0x10000L; } matrix->xx = temp[0]; matrix->yx = temp[1]; matrix->xy = temp[2]; matrix->yy = temp[3]; /* note that the offsets must be expressed in integer font units */ offset->x = temp[4] >> 16; offset->y = temp[5] >> 16; } static void t42_parse_encoding( T42_Face face, T42_Loader loader ) { T42_Parser parser = &loader->parser; FT_Byte* cur; FT_Byte* limit = parser->root.limit; PSAux_Service psaux = (PSAux_Service)face->psaux; T1_Skip_Spaces( parser ); cur = parser->root.cursor; if ( cur >= limit ) { FT_ERROR(( "t42_parse_encoding: out of bounds!\n" )); parser->root.error = T42_Err_Invalid_File_Format; return; } /* if we have a number or `[', the encoding is an array, */ /* and we must load it now */ if ( ft_isdigit( *cur ) || *cur == '[' ) { T1_Encoding encode = &face->type1.encoding; FT_UInt count, n; PS_Table char_table = &loader->encoding_table; FT_Memory memory = parser->root.memory; FT_Error error; FT_Bool only_immediates = 0; /* read the number of entries in the encoding; should be 256 */ if ( *cur == '[' ) { count = 256; only_immediates = 1; parser->root.cursor++; } else count = (FT_UInt)T1_ToInt( parser ); T1_Skip_Spaces( parser ); if ( parser->root.cursor >= limit ) return; /* we use a T1_Table to store our charnames */ loader->num_chars = encode->num_chars = count; if ( FT_NEW_ARRAY( encode->char_index, count ) || FT_NEW_ARRAY( encode->char_name, count ) || FT_SET_ERROR( psaux->ps_table_funcs->init( char_table, count, memory ) ) ) { parser->root.error = error; return; } /* We need to `zero' out encoding_table.elements */ for ( n = 0; n < count; n++ ) { char* notdef = (char *)".notdef"; T1_Add_Table( char_table, n, notdef, 8 ); } /* Now we need to read records of the form */ /* */ /* ... charcode /charname ... */ /* */ /* for each entry in our table. */ /* */ /* We simply look for a number followed by an immediate */ /* name. Note that this ignores correctly the sequence */ /* that is often seen in type42 fonts: */ /* */ /* 0 1 255 { 1 index exch /.notdef put } for dup */ /* */ /* used to clean the encoding array before anything else. */ /* */ /* Alternatively, if the array is directly given as */ /* */ /* /Encoding [ ... ] */ /* */ /* we only read immediates. */ n = 0; T1_Skip_Spaces( parser ); while ( parser->root.cursor < limit ) { cur = parser->root.cursor; /* we stop when we encounter `def' or `]' */ if ( *cur == 'd' && cur + 3 < limit ) { if ( cur[1] == 'e' && cur[2] == 'f' && t42_is_space( cur[3] ) )
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -