📄 cffparse.c
字号:
/***************************************************************************//* *//* cffparse.c *//* *//* CFF token stream parser (body) *//* *//* Copyright 1996-2001, 2002, 2003, 2004, 2007 by *//* David Turner, Robert Wilhelm, and Werner Lemberg. *//* *//* 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 <ft2build.h>#include "cffparse.h"#include FT_INTERNAL_STREAM_H#include "cfferrs.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_cffparse enum { cff_kind_none = 0, cff_kind_num, cff_kind_fixed, cff_kind_fixed_thousand, cff_kind_string, cff_kind_bool, cff_kind_delta, cff_kind_callback, cff_kind_max /* do not remove */ }; /* now generate handlers for the most simple fields */ typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser ); typedef struct CFF_Field_Handler_ { int kind; int code; FT_UInt offset; FT_Byte size; CFF_Field_Reader reader; FT_UInt array_max; FT_UInt count_offset; } CFF_Field_Handler; FT_LOCAL_DEF( void ) cff_parser_init( CFF_Parser parser, FT_UInt code, void* object ) { FT_MEM_ZERO( parser, sizeof ( *parser ) ); parser->top = parser->stack; parser->object_code = code; parser->object = object; } /* read an integer */ static FT_Long cff_parse_integer( FT_Byte* start, FT_Byte* limit ) { FT_Byte* p = start; FT_Int v = *p++; FT_Long val = 0; if ( v == 28 ) { if ( p + 2 > limit ) goto Bad; val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] ); p += 2; } else if ( v == 29 ) { if ( p + 4 > limit ) goto Bad; val = ( (FT_Long)p[0] << 24 ) | ( (FT_Long)p[1] << 16 ) | ( (FT_Long)p[2] << 8 ) | p[3]; p += 4; } else if ( v < 247 ) { val = v - 139; } else if ( v < 251 ) { if ( p + 1 > limit ) goto Bad; val = ( v - 247 ) * 256 + p[0] + 108; p++; } else { if ( p + 1 > limit ) goto Bad; val = -( v - 251 ) * 256 - p[0] - 108; p++; } Exit: return val; Bad: val = 0; goto Exit; } /* read a real */ static FT_Fixed cff_parse_real( FT_Byte* start, FT_Byte* limit, FT_Int power_ten ) { FT_Byte* p = start; FT_Long num, divider, result, exponent; FT_Int sign = 0, exponent_sign = 0; FT_UInt nib; FT_UInt phase; result = 0; num = 0; divider = 1; /* first of all, read the integer part */ phase = 4; for (;;) { /* If we entered this iteration with phase == 4, we need to */ /* read a new byte. This also skips past the initial 0x1E. */ if ( phase ) { p++; /* Make sure we don't read past the end. */ if ( p >= limit ) goto Bad; } /* Get the nibble. */ nib = ( p[0] >> phase ) & 0xF; phase = 4 - phase; if ( nib == 0xE ) sign = 1; else if ( nib > 9 ) break; else result = result * 10 + nib; } /* read decimal part, if any */ if ( nib == 0xa ) for (;;) { /* If we entered this iteration with phase == 4, we need */ /* to read a new byte. */ if ( phase ) { p++; /* Make sure we don't read past the end. */ if ( p >= limit ) goto Bad; } /* Get the nibble. */ nib = ( p[0] >> phase ) & 0xF; phase = 4 - phase; if ( nib >= 10 ) break; if ( divider < 10000000L ) { num = num * 10 + nib; divider *= 10; } } /* read exponent, if any */ if ( nib == 12 ) { exponent_sign = 1; nib = 11; } if ( nib == 11 ) { exponent = 0; for (;;) { /* If we entered this iteration with phase == 4, we need */ /* to read a new byte. */ if ( phase ) { p++; /* Make sure we don't read past the end. */ if ( p >= limit ) goto Bad; } /* Get the nibble. */ nib = ( p[0] >> phase ) & 0xF; phase = 4 - phase; if ( nib >= 10 ) break; exponent = exponent * 10 + nib; } if ( exponent_sign ) exponent = -exponent; power_ten += (FT_Int)exponent; } /* raise to power of ten if needed */ while ( power_ten > 0 ) { result = result * 10; num = num * 10; power_ten--; } while ( power_ten < 0 ) { result = result / 10; divider = divider * 10; power_ten++; } /* Move the integer part into the high 16 bits. */ result <<= 16; /* Place the decimal part into the low 16 bits. */ if ( num ) result |= FT_DivFix( num, divider ); if ( sign ) result = -result; Exit: return result; Bad: result = 0; goto Exit; } /* read a number, either integer or real */ static FT_Long cff_parse_num( FT_Byte** d ) { return ( **d == 30 ? ( cff_parse_real ( d[0], d[1], 0 ) >> 16 ) : cff_parse_integer( d[0], d[1] ) ); } /* read a floating point number, either integer or real */ static FT_Fixed cff_parse_fixed( FT_Byte** d ) { return ( **d == 30 ? cff_parse_real ( d[0], d[1], 0 ) : cff_parse_integer( d[0], d[1] ) << 16 ); } /* read a floating point number, either integer or real, */ /* but return 1000 times the number read in. */ static FT_Fixed cff_parse_fixed_thousand( FT_Byte** d ) { return **d == 30 ? cff_parse_real ( d[0], d[1], 3 ) : (FT_Fixed)FT_MulFix( cff_parse_integer( d[0], d[1] ) << 16, 1000 ); } static FT_Error cff_parse_font_matrix( CFF_Parser parser ) { CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; FT_Matrix* matrix = &dict->font_matrix; FT_Vector* offset = &dict->font_offset; FT_UShort* upm = &dict->units_per_em; FT_Byte** data = parser->stack; FT_Error error; FT_Fixed temp; error = CFF_Err_Stack_Underflow; if ( parser->top >= parser->stack + 6 ) { matrix->xx = cff_parse_fixed_thousand( data++ ); matrix->yx = cff_parse_fixed_thousand( data++ ); matrix->xy = cff_parse_fixed_thousand( data++ ); matrix->yy = cff_parse_fixed_thousand( data++ ); offset->x = cff_parse_fixed_thousand( data++ ); offset->y = cff_parse_fixed_thousand( data ); temp = FT_ABS( matrix->yy ); *upm = (FT_UShort)FT_DivFix( 0x10000L, FT_DivFix( temp, 1000 ) ); if ( temp != 0x10000L ) { matrix->xx = FT_DivFix( matrix->xx, temp ); matrix->yx = FT_DivFix( matrix->yx, temp ); matrix->xy = FT_DivFix( matrix->xy, temp );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -