diff --git a/src/cff/cf2font.h b/src/cff/cf2font.h index c86b8f83f..32063c781 100644 --- a/src/cff/cf2font.h +++ b/src/cff/cf2font.h @@ -46,8 +46,8 @@ FT_BEGIN_HEADER - -#define CF2_OPERAND_STACK_SIZE 193/* TODO: this is temporary for CFF2 */ +#define CF2_CFF2_STACK_SIZE 193 +#define CF2_OPERAND_STACK_SIZE 48 #define CF2_MAX_SUBR 16 /* maximum subroutine nesting; */ /* only 10 are allowed but there exist */ /* fonts like `HiraKakuProN-W3.ttf' */ diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c index fd95a6b2a..93c538313 100644 --- a/src/cff/cf2ft.c +++ b/src/cff/cf2ft.c @@ -425,6 +425,16 @@ return &decoder->cff->vstore; } + /* get maxstack value from CFF2 Top DICT */ + /* Note: CFF2 Font DICT contains only the default maxstack value */ + FT_LOCAL_DEF ( FT_UInt ) + cf2_getMaxstack( CFF_Decoder* decoder ) + { + FT_ASSERT( decoder && decoder->cff ); + + return decoder->cff->top_font.font_dict.maxstack; + } + /* get normalized design vector for current render request */ /* returns pointer and length */ /* if blend struct is not initialized, return length zero */ diff --git a/src/cff/cf2ft.h b/src/cff/cf2ft.h index 7c1311aab..c5dbba060 100644 --- a/src/cff/cf2ft.h +++ b/src/cff/cf2ft.h @@ -67,6 +67,9 @@ FT_BEGIN_HEADER FT_LOCAL( CFF_VStore ) cf2_getVStore( CFF_Decoder* decoder ); + FT_LOCAL_DEF ( FT_UInt ) + cf2_getMaxstack( CFF_Decoder* decoder ); + FT_LOCAL_DEF( void ) cf2_getNormalizedVector( CFF_Decoder* decoder, diff --git a/src/cff/cf2intrp.c b/src/cff/cf2intrp.c index 0cbee559a..9b190775a 100644 --- a/src/cff/cf2intrp.c +++ b/src/cff/cf2intrp.c @@ -474,6 +474,7 @@ CF2_Fixed hintOriginY = curY; CF2_Stack opStack = NULL; + FT_UInt stackSize = font->isCFF2 ? CF2_CFF2_STACK_SIZE : CF2_OPERAND_STACK_SIZE; FT_Byte op1; /* first opcode byte */ CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */ @@ -561,7 +562,14 @@ */ /* allocate an operand stack */ - opStack = cf2_stack_init( memory, error ); + if ( font->isCFF2 ) + { + /* CFF2 font may increase the operand stack size */ + FT_UInt maxstack = cf2_getMaxstack( decoder ); + if ( maxstack > stackSize ) + stackSize = maxstack; + } + opStack = cf2_stack_init( memory, error, stackSize ); if ( !opStack ) { lastError = FT_THROW( Out_Of_Memory ); diff --git a/src/cff/cf2stack.c b/src/cff/cf2stack.c index 5001b68cf..063485047 100644 --- a/src/cff/cf2stack.c +++ b/src/cff/cf2stack.c @@ -51,7 +51,8 @@ /* `error'). */ FT_LOCAL_DEF( CF2_Stack ) cf2_stack_init( FT_Memory memory, - FT_Error* e ) + FT_Error* e, + FT_UInt stackSize ) { FT_Error error = FT_Err_Ok; /* for FT_QNEW */ @@ -63,9 +64,18 @@ /* initialize the structure; FT_QNEW zeroes it */ stack->memory = memory; stack->error = e; - stack->top = &stack->buffer[0]; /* empty stack */ } + /* allocate the stack buffer */ + if ( FT_NEW_ARRAY( stack->buffer, stackSize ) ) + { + FT_FREE( stack ); + return NULL; + } + + stack->stackSize = stackSize; + stack->top = stack->buffer; /* empty stack */ + return stack; } @@ -77,6 +87,8 @@ { FT_Memory memory = stack->memory; + /* free the buffer */ + FT_FREE( stack->buffer ); /* free the main structure */ FT_FREE( stack ); @@ -87,7 +99,7 @@ FT_LOCAL_DEF( CF2_UInt ) cf2_stack_count( CF2_Stack stack ) { - return (CF2_UInt)( stack->top - &stack->buffer[0] ); + return (CF2_UInt)( stack->top - stack->buffer ); } @@ -95,7 +107,7 @@ cf2_stack_pushInt( CF2_Stack stack, CF2_Int val ) { - if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] ) + if ( stack->top == stack->buffer + stack->stackSize ) { CF2_SET_ERROR( stack->error, Stack_Overflow ); return; /* stack overflow */ @@ -111,7 +123,7 @@ cf2_stack_pushFixed( CF2_Stack stack, CF2_Fixed val ) { - if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] ) + if ( stack->top == stack->buffer + stack->stackSize ) { CF2_SET_ERROR( stack->error, Stack_Overflow ); return; /* stack overflow */ @@ -127,7 +139,7 @@ FT_LOCAL_DEF( CF2_Int ) cf2_stack_popInt( CF2_Stack stack ) { - if ( stack->top == &stack->buffer[0] ) + if ( stack->top == stack->buffer ) { CF2_SET_ERROR( stack->error, Stack_Underflow ); return 0; /* underflow */ @@ -149,7 +161,7 @@ FT_LOCAL_DEF( CF2_Fixed ) cf2_stack_popFixed( CF2_Stack stack ) { - if ( stack->top == &stack->buffer[0] ) + if ( stack->top == stack->buffer ) { CF2_SET_ERROR( stack->error, Stack_Underflow ); return cf2_intToFixed( 0 ); /* underflow */ @@ -175,7 +187,7 @@ cf2_stack_getReal( CF2_Stack stack, CF2_UInt idx ) { - FT_ASSERT( cf2_stack_count( stack ) <= CF2_OPERAND_STACK_SIZE ); + FT_ASSERT( cf2_stack_count( stack ) <= stack->stackSize ); if ( idx >= cf2_stack_count( stack ) ) { @@ -306,7 +318,7 @@ FT_LOCAL_DEF( void ) cf2_stack_clear( CF2_Stack stack ) { - stack->top = &stack->buffer[0]; + stack->top = stack->buffer; } diff --git a/src/cff/cf2stack.h b/src/cff/cf2stack.h index acec07470..03de345d3 100644 --- a/src/cff/cf2stack.h +++ b/src/cff/cf2stack.h @@ -62,15 +62,17 @@ FT_BEGIN_HEADER { FT_Memory memory; FT_Error* error; - CF2_StackNumber buffer[CF2_OPERAND_STACK_SIZE]; + CF2_StackNumber* buffer; CF2_StackNumber* top; + FT_UInt stackSize; } CF2_StackRec, *CF2_Stack; FT_LOCAL( CF2_Stack ) cf2_stack_init( FT_Memory memory, - FT_Error* error ); + FT_Error* error, + FT_UInt stackSize ); FT_LOCAL( void ) cf2_stack_free( CF2_Stack stack ); diff --git a/src/cff/cffload.c b/src/cff/cffload.c index fd0162f25..4c65c94e6 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1844,6 +1844,9 @@ Exit: top->cid_ordering = 0xFFFFU; top->cid_font_name = 0xFFFFU; + /* set default stack size */ + top->maxstack = cff2 ? 193 : 48; + if ( idx->count ) /* count is nonzero for a real index */ error = cff_index_access_element( idx, font_index, &dict, &dict_len ); else