-/***************************************************************************/\r
-/* */\r
-/* cffparse.c */\r
-/* */\r
-/* CFF token stream parser (body) */\r
-/* */\r
-/* Copyright 1996-2001, 2002, 2003, 2004, 2007 by */\r
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */\r
-/* */\r
-/* This file is part of the FreeType project, and may only be used, */\r
-/* modified, and distributed under the terms of the FreeType project */\r
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */\r
-/* this file you indicate that you have read the license and */\r
-/* understand and accept it fully. */\r
-/* */\r
-/***************************************************************************/\r
-\r
-\r
-#include <ft2build.h>\r
-#include "cffparse.h"\r
-#include FT_INTERNAL_STREAM_H\r
-\r
-#include "cfferrs.h"\r
-\r
-\r
- /*************************************************************************/\r
- /* */\r
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */\r
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */\r
- /* messages during execution. */\r
- /* */\r
-#undef FT_COMPONENT\r
-#define FT_COMPONENT trace_cffparse\r
-\r
-\r
- enum\r
- {\r
- cff_kind_none = 0,\r
- cff_kind_num,\r
- cff_kind_fixed,\r
- cff_kind_fixed_thousand,\r
- cff_kind_string,\r
- cff_kind_bool,\r
- cff_kind_delta,\r
- cff_kind_callback,\r
-\r
- cff_kind_max /* do not remove */\r
- };\r
-\r
-\r
- /* now generate handlers for the most simple fields */\r
- typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser );\r
-\r
- typedef struct CFF_Field_Handler_\r
- {\r
- int kind;\r
- int code;\r
- FT_UInt offset;\r
- FT_Byte size;\r
- CFF_Field_Reader reader;\r
- FT_UInt array_max;\r
- FT_UInt count_offset;\r
-\r
- } CFF_Field_Handler;\r
-\r
-\r
- FT_LOCAL_DEF( void )\r
- cff_parser_init( CFF_Parser parser,\r
- FT_UInt code,\r
- void* object )\r
- {\r
- FT_MEM_ZERO( parser, sizeof ( *parser ) );\r
-\r
- parser->top = parser->stack;\r
- parser->object_code = code;\r
- parser->object = object;\r
- }\r
-\r
-\r
- /* read an integer */\r
- static FT_Long\r
- cff_parse_integer( FT_Byte* start,\r
- FT_Byte* limit )\r
- {\r
- FT_Byte* p = start;\r
- FT_Int v = *p++;\r
- FT_Long val = 0;\r
-\r
-\r
- if ( v == 28 )\r
- {\r
- if ( p + 2 > limit )\r
- goto Bad;\r
-\r
- val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );\r
- p += 2;\r
- }\r
- else if ( v == 29 )\r
- {\r
- if ( p + 4 > limit )\r
- goto Bad;\r
-\r
- val = ( (FT_Long)p[0] << 24 ) |\r
- ( (FT_Long)p[1] << 16 ) |\r
- ( (FT_Long)p[2] << 8 ) |\r
- p[3];\r
- p += 4;\r
- }\r
- else if ( v < 247 )\r
- {\r
- val = v - 139;\r
- }\r
- else if ( v < 251 )\r
- {\r
- if ( p + 1 > limit )\r
- goto Bad;\r
-\r
- val = ( v - 247 ) * 256 + p[0] + 108;\r
- p++;\r
- }\r
- else\r
- {\r
- if ( p + 1 > limit )\r
- goto Bad;\r
-\r
- val = -( v - 251 ) * 256 - p[0] - 108;\r
- p++;\r
- }\r
-\r
- Exit:\r
- return val;\r
-\r
- Bad:\r
- val = 0;\r
- goto Exit;\r
- }\r
-\r
-\r
- /* read a real */\r
- static FT_Fixed\r
- cff_parse_real( FT_Byte* start,\r
- FT_Byte* limit,\r
- FT_Int power_ten )\r
- {\r
- FT_Byte* p = start;\r
- FT_Long num, divider, result, exponent;\r
- FT_Int sign = 0, exponent_sign = 0;\r
- FT_UInt nib;\r
- FT_UInt phase;\r
-\r
-\r
- result = 0;\r
- num = 0;\r
- divider = 1;\r
-\r
- /* first of all, read the integer part */\r
- phase = 4;\r
-\r
- for (;;)\r
- {\r
- /* If we entered this iteration with phase == 4, we need to */\r
- /* read a new byte. This also skips past the initial 0x1E. */\r
- if ( phase )\r
- {\r
- p++;\r
-\r
- /* Make sure we don't read past the end. */\r
- if ( p >= limit )\r
- goto Bad;\r
- }\r
-\r
- /* Get the nibble. */\r
- nib = ( p[0] >> phase ) & 0xF;\r
- phase = 4 - phase;\r
-\r
- if ( nib == 0xE )\r
- sign = 1;\r
- else if ( nib > 9 )\r
- break;\r
- else\r
- result = result * 10 + nib;\r
- }\r
-\r
- /* read decimal part, if any */\r
- if ( nib == 0xa )\r
- for (;;)\r
- {\r
- /* If we entered this iteration with phase == 4, we need */\r
- /* to read a new byte. */\r
- if ( phase )\r
- {\r
- p++;\r
-\r
- /* Make sure we don't read past the end. */\r
- if ( p >= limit )\r
- goto Bad;\r
- }\r
-\r
- /* Get the nibble. */\r
- nib = ( p[0] >> phase ) & 0xF;\r
- phase = 4 - phase;\r
- if ( nib >= 10 )\r
- break;\r
-\r
- if ( divider < 10000000L )\r
- {\r
- num = num * 10 + nib;\r
- divider *= 10;\r
- }\r
- }\r
-\r
- /* read exponent, if any */\r
- if ( nib == 12 )\r
- {\r
- exponent_sign = 1;\r
- nib = 11;\r
- }\r
-\r
- if ( nib == 11 )\r
- {\r
- exponent = 0;\r
-\r
- for (;;)\r
- {\r
- /* If we entered this iteration with phase == 4, we need */\r
- /* to read a new byte. */\r
- if ( phase )\r
- {\r
- p++;\r
-\r
- /* Make sure we don't read past the end. */\r
- if ( p >= limit )\r
- goto Bad;\r
- }\r
-\r
- /* Get the nibble. */\r
- nib = ( p[0] >> phase ) & 0xF;\r
- phase = 4 - phase;\r
- if ( nib >= 10 )\r
- break;\r
-\r
- exponent = exponent * 10 + nib;\r
- }\r
-\r
- if ( exponent_sign )\r
- exponent = -exponent;\r
-\r
- power_ten += (FT_Int)exponent;\r
- }\r
-\r
- /* raise to power of ten if needed */\r
- while ( power_ten > 0 )\r
- {\r
- result = result * 10;\r
- num = num * 10;\r
-\r
- power_ten--;\r
- }\r
-\r
- while ( power_ten < 0 )\r
- {\r
- result = result / 10;\r
- divider = divider * 10;\r
-\r
- power_ten++;\r
- }\r
-\r
- /* Move the integer part into the high 16 bits. */\r
- result <<= 16;\r
-\r
- /* Place the decimal part into the low 16 bits. */\r
- if ( num )\r
- result |= FT_DivFix( num, divider );\r
-\r
- if ( sign )\r
- result = -result;\r
-\r
- Exit:\r
- return result;\r
-\r
- Bad:\r
- result = 0;\r
- goto Exit;\r
- }\r
-\r
-\r
- /* read a number, either integer or real */\r
- static FT_Long\r
- cff_parse_num( FT_Byte** d )\r
- {\r
- return ( **d == 30 ? ( cff_parse_real ( d[0], d[1], 0 ) >> 16 )\r
- : cff_parse_integer( d[0], d[1] ) );\r
- }\r
-\r
-\r
- /* read a floating point number, either integer or real */\r
- static FT_Fixed\r
- cff_parse_fixed( FT_Byte** d )\r
- {\r
- return ( **d == 30 ? cff_parse_real ( d[0], d[1], 0 )\r
- : cff_parse_integer( d[0], d[1] ) << 16 );\r
- }\r
-\r
- /* read a floating point number, either integer or real, */\r
- /* but return 1000 times the number read in. */\r
- static FT_Fixed\r
- cff_parse_fixed_thousand( FT_Byte** d )\r
- {\r
- return **d ==\r
- 30 ? cff_parse_real ( d[0], d[1], 3 )\r
- : (FT_Fixed)FT_MulFix( cff_parse_integer( d[0], d[1] ) << 16, 1000 );\r
- }\r
-\r
- static FT_Error\r
- cff_parse_font_matrix( CFF_Parser parser )\r
- {\r
- CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;\r
- FT_Matrix* matrix = &dict->font_matrix;\r
- FT_Vector* offset = &dict->font_offset;\r
- FT_UShort* upm = &dict->units_per_em;\r
- FT_Byte** data = parser->stack;\r
- FT_Error error;\r
- FT_Fixed temp;\r
-\r
-\r
- error = CFF_Err_Stack_Underflow;\r
-\r
- if ( parser->top >= parser->stack + 6 )\r
- {\r
- matrix->xx = cff_parse_fixed_thousand( data++ );\r
- matrix->yx = cff_parse_fixed_thousand( data++ );\r
- matrix->xy = cff_parse_fixed_thousand( data++ );\r
- matrix->yy = cff_parse_fixed_thousand( data++ );\r
- offset->x = cff_parse_fixed_thousand( data++ );\r
- offset->y = cff_parse_fixed_thousand( data );\r
-\r
- temp = FT_ABS( matrix->yy );\r
-\r
- *upm = (FT_UShort)FT_DivFix( 0x10000L, FT_DivFix( temp, 1000 ) );\r
-\r
- if ( temp != 0x10000L )\r
- {\r
- matrix->xx = FT_DivFix( matrix->xx, temp );\r
- matrix->yx = FT_DivFix( matrix->yx, temp );\r
- matrix->xy = FT_DivFix( matrix->xy, temp );\r
- matrix->yy = FT_DivFix( matrix->yy, temp );\r
- offset->x = FT_DivFix( offset->x, temp );\r
- offset->y = FT_DivFix( offset->y, temp );\r
- }\r
-\r
- /* note that the offsets must be expressed in integer font units */\r
- offset->x >>= 16;\r
- offset->y >>= 16;\r
-\r
- error = CFF_Err_Ok;\r
- }\r
-\r
- return error;\r
- }\r
-\r
-\r
- static FT_Error\r
- cff_parse_font_bbox( CFF_Parser parser )\r
- {\r
- CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;\r
- FT_BBox* bbox = &dict->font_bbox;\r
- FT_Byte** data = parser->stack;\r
- FT_Error error;\r
-\r
-\r
- error = CFF_Err_Stack_Underflow;\r
-\r
- if ( parser->top >= parser->stack + 4 )\r
- {\r
- bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );\r
- bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );\r
- bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );\r
- bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) );\r
- error = CFF_Err_Ok;\r
- }\r
-\r
- return error;\r
- }\r
-\r
-\r
- static FT_Error\r
- cff_parse_private_dict( CFF_Parser parser )\r
- {\r
- CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;\r
- FT_Byte** data = parser->stack;\r
- FT_Error error;\r
-\r
-\r
- error = CFF_Err_Stack_Underflow;\r
-\r
- if ( parser->top >= parser->stack + 2 )\r
- {\r
- dict->private_size = cff_parse_num( data++ );\r
- dict->private_offset = cff_parse_num( data );\r
- error = CFF_Err_Ok;\r
- }\r
-\r
- return error;\r
- }\r
-\r
-\r
- static FT_Error\r
- cff_parse_cid_ros( CFF_Parser parser )\r
- {\r
- CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;\r
- FT_Byte** data = parser->stack;\r
- FT_Error error;\r
-\r
-\r
- error = CFF_Err_Stack_Underflow;\r
-\r
- if ( parser->top >= parser->stack + 3 )\r
- {\r
- dict->cid_registry = (FT_UInt)cff_parse_num ( data++ );\r
- dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ );\r
- dict->cid_supplement = (FT_ULong)cff_parse_num( data );\r
- error = CFF_Err_Ok;\r
- }\r
-\r
- return error;\r
- }\r
-\r
-\r
-#define CFF_FIELD_NUM( code, name ) \\r
- CFF_FIELD( code, name, cff_kind_num )\r
-#define CFF_FIELD_FIXED( code, name ) \\r
- CFF_FIELD( code, name, cff_kind_fixed )\r
-#define CFF_FIELD_FIXED_1000( code, name ) \\r
- CFF_FIELD( code, name, cff_kind_fixed_thousand )\r
-#define CFF_FIELD_STRING( code, name ) \\r
- CFF_FIELD( code, name, cff_kind_string )\r
-#define CFF_FIELD_BOOL( code, name ) \\r
- CFF_FIELD( code, name, cff_kind_bool )\r
-#define CFF_FIELD_DELTA( code, name, max ) \\r
- CFF_FIELD( code, name, cff_kind_delta )\r
-\r
-#define CFF_FIELD_CALLBACK( code, name ) \\r
- { \\r
- cff_kind_callback, \\r
- code | CFFCODE, \\r
- 0, 0, \\r
- cff_parse_ ## name, \\r
- 0, 0 \\r
- },\r
-\r
-#undef CFF_FIELD\r
-#define CFF_FIELD( code, name, kind ) \\r
- { \\r
- kind, \\r
- code | CFFCODE, \\r
- FT_FIELD_OFFSET( name ), \\r
- FT_FIELD_SIZE( name ), \\r
- 0, 0, 0 \\r
- },\r
-\r
-#undef CFF_FIELD_DELTA\r
-#define CFF_FIELD_DELTA( code, name, max ) \\r
- { \\r
- cff_kind_delta, \\r
- code | CFFCODE, \\r
- FT_FIELD_OFFSET( name ), \\r
- FT_FIELD_SIZE_DELTA( name ), \\r
- 0, \\r
- max, \\r
- FT_FIELD_OFFSET( num_ ## name ) \\r
- },\r
-\r
-#define CFFCODE_TOPDICT 0x1000\r
-#define CFFCODE_PRIVATE 0x2000\r
-\r
- static const CFF_Field_Handler cff_field_handlers[] =\r
- {\r
-\r
-#include "cfftoken.h"\r
-\r
- { 0, 0, 0, 0, 0, 0, 0 }\r
- };\r
-\r
-\r
- FT_LOCAL_DEF( FT_Error )\r
- cff_parser_run( CFF_Parser parser,\r
- FT_Byte* start,\r
- FT_Byte* limit )\r
- {\r
- FT_Byte* p = start;\r
- FT_Error error = CFF_Err_Ok;\r
-\r
-\r
- parser->top = parser->stack;\r
- parser->start = start;\r
- parser->limit = limit;\r
- parser->cursor = start;\r
-\r
- while ( p < limit )\r
- {\r
- FT_UInt v = *p;\r
-\r
-\r
- if ( v >= 27 && v != 31 )\r
- {\r
- /* it's a number; we will push its position on the stack */\r
- if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )\r
- goto Stack_Overflow;\r
-\r
- *parser->top ++ = p;\r
-\r
- /* now, skip it */\r
- if ( v == 30 )\r
- {\r
- /* skip real number */\r
- p++;\r
- for (;;)\r
- {\r
- if ( p >= limit )\r
- goto Syntax_Error;\r
- v = p[0] >> 4;\r
- if ( v == 15 )\r
- break;\r
- v = p[0] & 0xF;\r
- if ( v == 15 )\r
- break;\r
- p++;\r
- }\r
- }\r
- else if ( v == 28 )\r
- p += 2;\r
- else if ( v == 29 )\r
- p += 4;\r
- else if ( v > 246 )\r
- p += 1;\r
- }\r
- else\r
- {\r
- /* This is not a number, hence it's an operator. Compute its code */\r
- /* and look for it in our current list. */\r
-\r
- FT_UInt code;\r
- FT_UInt num_args = (FT_UInt)\r
- ( parser->top - parser->stack );\r
- const CFF_Field_Handler* field;\r
-\r
-\r
- *parser->top = p;\r
- code = v;\r
- if ( v == 12 )\r
- {\r
- /* two byte operator */\r
- p++;\r
- if ( p >= limit )\r
- goto Syntax_Error;\r
-\r
- code = 0x100 | p[0];\r
- }\r
- code = code | parser->object_code;\r
-\r
- for ( field = cff_field_handlers; field->kind; field++ )\r
- {\r
- if ( field->code == (FT_Int)code )\r
- {\r
- /* we found our field's handler; read it */\r
- FT_Long val;\r
- FT_Byte* q = (FT_Byte*)parser->object + field->offset;\r
-\r
-\r
- /* check that we have enough arguments -- except for */\r
- /* delta encoded arrays, which can be empty */\r
- if ( field->kind != cff_kind_delta && num_args < 1 )\r
- goto Stack_Underflow;\r
-\r
- switch ( field->kind )\r
- {\r
- case cff_kind_bool:\r
- case cff_kind_string:\r
- case cff_kind_num:\r
- val = cff_parse_num( parser->stack );\r
- goto Store_Number;\r
-\r
- case cff_kind_fixed:\r
- val = cff_parse_fixed( parser->stack );\r
- goto Store_Number;\r
-\r
- case cff_kind_fixed_thousand:\r
- val = cff_parse_fixed_thousand( parser->stack );\r
-\r
- Store_Number:\r
- switch ( field->size )\r
- {\r
- case (8 / FT_CHAR_BIT):\r
- *(FT_Byte*)q = (FT_Byte)val;\r
- break;\r
-\r
- case (16 / FT_CHAR_BIT):\r
- *(FT_Short*)q = (FT_Short)val;\r
- break;\r
-\r
- case (32 / FT_CHAR_BIT):\r
- *(FT_Int32*)q = (FT_Int)val;\r
- break;\r
-\r
- default: /* for 64-bit systems */\r
- *(FT_Long*)q = val;\r
- }\r
- break;\r
-\r
- case cff_kind_delta:\r
- {\r
- FT_Byte* qcount = (FT_Byte*)parser->object +\r
- field->count_offset;\r
-\r
- FT_Byte** data = parser->stack;\r
-\r
-\r
- if ( num_args > field->array_max )\r
- num_args = field->array_max;\r
-\r
- /* store count */\r
- *qcount = (FT_Byte)num_args;\r
-\r
- val = 0;\r
- while ( num_args > 0 )\r
- {\r
- val += cff_parse_num( data++ );\r
- switch ( field->size )\r
- {\r
- case (8 / FT_CHAR_BIT):\r
- *(FT_Byte*)q = (FT_Byte)val;\r
- break;\r
-\r
- case (16 / FT_CHAR_BIT):\r
- *(FT_Short*)q = (FT_Short)val;\r
- break;\r
-\r
- case (32 / FT_CHAR_BIT):\r
- *(FT_Int32*)q = (FT_Int)val;\r
- break;\r
-\r
- default: /* for 64-bit systems */\r
- *(FT_Long*)q = val;\r
- }\r
-\r
- q += field->size;\r
- num_args--;\r
- }\r
- }\r
- break;\r
-\r
- default: /* callback */\r
- error = field->reader( parser );\r
- if ( error )\r
- goto Exit;\r
- }\r
- goto Found;\r
- }\r
- }\r
-\r
- /* this is an unknown operator, or it is unsupported; */\r
- /* we will ignore it for now. */\r
-\r
- Found:\r
- /* clear stack */\r
- parser->top = parser->stack;\r
- }\r
- p++;\r
- }\r
-\r
- Exit:\r
- return error;\r
-\r
- Stack_Overflow:\r
- error = CFF_Err_Invalid_Argument;\r
- goto Exit;\r
-\r
- Stack_Underflow:\r
- error = CFF_Err_Invalid_Argument;\r
- goto Exit;\r
-\r
- Syntax_Error:\r
- error = CFF_Err_Invalid_Argument;\r
- goto Exit;\r
- }\r
-\r
-\r
-/* END */\r
+/***************************************************************************/
+/* */
+/* 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 );
+ matrix->yy = FT_DivFix( matrix->yy, temp );
+ offset->x = FT_DivFix( offset->x, temp );
+ offset->y = FT_DivFix( offset->y, temp );
+ }
+
+ /* note that the offsets must be expressed in integer font units */
+ offset->x >>= 16;
+ offset->y >>= 16;
+
+ error = CFF_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ cff_parse_font_bbox( CFF_Parser parser )
+ {
+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
+ FT_BBox* bbox = &dict->font_bbox;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = CFF_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 4 )
+ {
+ bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
+ bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
+ bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
+ bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) );
+ error = CFF_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ cff_parse_private_dict( CFF_Parser parser )
+ {
+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = CFF_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 2 )
+ {
+ dict->private_size = cff_parse_num( data++ );
+ dict->private_offset = cff_parse_num( data );
+ error = CFF_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
+ cff_parse_cid_ros( CFF_Parser parser )
+ {
+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
+ FT_Byte** data = parser->stack;
+ FT_Error error;
+
+
+ error = CFF_Err_Stack_Underflow;
+
+ if ( parser->top >= parser->stack + 3 )
+ {
+ dict->cid_registry = (FT_UInt)cff_parse_num ( data++ );
+ dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ );
+ dict->cid_supplement = (FT_ULong)cff_parse_num( data );
+ error = CFF_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+#define CFF_FIELD_NUM( code, name ) \
+ CFF_FIELD( code, name, cff_kind_num )
+#define CFF_FIELD_FIXED( code, name ) \
+ CFF_FIELD( code, name, cff_kind_fixed )
+#define CFF_FIELD_FIXED_1000( code, name ) \
+ CFF_FIELD( code, name, cff_kind_fixed_thousand )
+#define CFF_FIELD_STRING( code, name ) \
+ CFF_FIELD( code, name, cff_kind_string )
+#define CFF_FIELD_BOOL( code, name ) \
+ CFF_FIELD( code, name, cff_kind_bool )
+#define CFF_FIELD_DELTA( code, name, max ) \
+ CFF_FIELD( code, name, cff_kind_delta )
+
+#define CFF_FIELD_CALLBACK( code, name ) \
+ { \
+ cff_kind_callback, \
+ code | CFFCODE, \
+ 0, 0, \
+ cff_parse_ ## name, \
+ 0, 0 \
+ },
+
+#undef CFF_FIELD
+#define CFF_FIELD( code, name, kind ) \
+ { \
+ kind, \
+ code | CFFCODE, \
+ FT_FIELD_OFFSET( name ), \
+ FT_FIELD_SIZE( name ), \
+ 0, 0, 0 \
+ },
+
+#undef CFF_FIELD_DELTA
+#define CFF_FIELD_DELTA( code, name, max ) \
+ { \
+ cff_kind_delta, \
+ code | CFFCODE, \
+ FT_FIELD_OFFSET( name ), \
+ FT_FIELD_SIZE_DELTA( name ), \
+ 0, \
+ max, \
+ FT_FIELD_OFFSET( num_ ## name ) \
+ },
+
+#define CFFCODE_TOPDICT 0x1000
+#define CFFCODE_PRIVATE 0x2000
+
+ static const CFF_Field_Handler cff_field_handlers[] =
+ {
+
+#include "cfftoken.h"
+
+ { 0, 0, 0, 0, 0, 0, 0 }
+ };
+
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_parser_run( CFF_Parser parser,
+ FT_Byte* start,
+ FT_Byte* limit )
+ {
+ FT_Byte* p = start;
+ FT_Error error = CFF_Err_Ok;
+
+
+ parser->top = parser->stack;
+ parser->start = start;
+ parser->limit = limit;
+ parser->cursor = start;
+
+ while ( p < limit )
+ {
+ FT_UInt v = *p;
+
+
+ if ( v >= 27 && v != 31 )
+ {
+ /* it's a number; we will push its position on the stack */
+ if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
+ goto Stack_Overflow;
+
+ *parser->top ++ = p;
+
+ /* now, skip it */
+ if ( v == 30 )
+ {
+ /* skip real number */
+ p++;
+ for (;;)
+ {
+ if ( p >= limit )
+ goto Syntax_Error;
+ v = p[0] >> 4;
+ if ( v == 15 )
+ break;
+ v = p[0] & 0xF;
+ if ( v == 15 )
+ break;
+ p++;
+ }
+ }
+ else if ( v == 28 )
+ p += 2;
+ else if ( v == 29 )
+ p += 4;
+ else if ( v > 246 )
+ p += 1;
+ }
+ else
+ {
+ /* This is not a number, hence it's an operator. Compute its code */
+ /* and look for it in our current list. */
+
+ FT_UInt code;
+ FT_UInt num_args = (FT_UInt)
+ ( parser->top - parser->stack );
+ const CFF_Field_Handler* field;
+
+
+ *parser->top = p;
+ code = v;
+ if ( v == 12 )
+ {
+ /* two byte operator */
+ p++;
+ if ( p >= limit )
+ goto Syntax_Error;
+
+ code = 0x100 | p[0];
+ }
+ code = code | parser->object_code;
+
+ for ( field = cff_field_handlers; field->kind; field++ )
+ {
+ if ( field->code == (FT_Int)code )
+ {
+ /* we found our field's handler; read it */
+ FT_Long val;
+ FT_Byte* q = (FT_Byte*)parser->object + field->offset;
+
+
+ /* check that we have enough arguments -- except for */
+ /* delta encoded arrays, which can be empty */
+ if ( field->kind != cff_kind_delta && num_args < 1 )
+ goto Stack_Underflow;
+
+ switch ( field->kind )
+ {
+ case cff_kind_bool:
+ case cff_kind_string:
+ case cff_kind_num:
+ val = cff_parse_num( parser->stack );
+ goto Store_Number;
+
+ case cff_kind_fixed:
+ val = cff_parse_fixed( parser->stack );
+ goto Store_Number;
+
+ case cff_kind_fixed_thousand:
+ val = cff_parse_fixed_thousand( parser->stack );
+
+ Store_Number:
+ switch ( field->size )
+ {
+ case (8 / FT_CHAR_BIT):
+ *(FT_Byte*)q = (FT_Byte)val;
+ break;
+
+ case (16 / FT_CHAR_BIT):
+ *(FT_Short*)q = (FT_Short)val;
+ break;
+
+ case (32 / FT_CHAR_BIT):
+ *(FT_Int32*)q = (FT_Int)val;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_Long*)q = val;
+ }
+ break;
+
+ case cff_kind_delta:
+ {
+ FT_Byte* qcount = (FT_Byte*)parser->object +
+ field->count_offset;
+
+ FT_Byte** data = parser->stack;
+
+
+ if ( num_args > field->array_max )
+ num_args = field->array_max;
+
+ /* store count */
+ *qcount = (FT_Byte)num_args;
+
+ val = 0;
+ while ( num_args > 0 )
+ {
+ val += cff_parse_num( data++ );
+ switch ( field->size )
+ {
+ case (8 / FT_CHAR_BIT):
+ *(FT_Byte*)q = (FT_Byte)val;
+ break;
+
+ case (16 / FT_CHAR_BIT):
+ *(FT_Short*)q = (FT_Short)val;
+ break;
+
+ case (32 / FT_CHAR_BIT):
+ *(FT_Int32*)q = (FT_Int)val;
+ break;
+
+ default: /* for 64-bit systems */
+ *(FT_Long*)q = val;
+ }
+
+ q += field->size;
+ num_args--;
+ }
+ }
+ break;
+
+ default: /* callback */
+ error = field->reader( parser );
+ if ( error )
+ goto Exit;
+ }
+ goto Found;
+ }
+ }
+
+ /* this is an unknown operator, or it is unsupported; */
+ /* we will ignore it for now. */
+
+ Found:
+ /* clear stack */
+ parser->top = parser->stack;
+ }
+ p++;
+ }
+
+ Exit:
+ return error;
+
+ Stack_Overflow:
+ error = CFF_Err_Invalid_Argument;
+ goto Exit;
+
+ Stack_Underflow:
+ error = CFF_Err_Invalid_Argument;
+ goto Exit;
+
+ Syntax_Error:
+ error = CFF_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+
+/* END */