[cff] Implement CFF2 support (1/2).
This commit does not contain the blend code for font variation support, which follows in another commit. You should ignore whitespace while inspecting this commit. * include/freetype/internal/tttypes.h (TT_Face): Add `isCFF2' member. * src/cff/cf2font.h (CF2_Font): Add `isCFF2' member. * src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Handle `isCFF2' flag. (cf2_getMaxstack): New function. * src/cff/cf2ft.h: Updated. * src/cff/cf2intrp.c (cf2_escRESERVED_38): New enum. (cf2_interpT2CharString): Handle CFF2 differences. Add tracing message for errors. * src/cff/cffdrivr.c (cff_get_glyph_name, cff_get_name_index): Update for CFF2. * src/cff/cffload.c (FT_FIXED_ONE): New macro. (cff_index_init, cff_index_load_offsets, cff_index_access_element, cff_index_get_name, cff_ft_select_get, cff_load_private_dict, cff_subfont_load, cff_font_load): Handle CFF2. * src/cff/cffload.h: Updated. * src/cff/cffobjs.c (cff_face_init): Handle CFF2. * src/cff/cffparse.c (cff_parse_maxstack): New function. (CFFCODE_TOPDICT, CFFCODE_PRIVATE): Removed * src/cff/cffparse.h (CFF2_MAX_STACK, CFF2_DEFAULT_STACK): New macros. (CFF2_CODE_TOPDICT, CFF2_CODE_FONTDICT, CFF2_CODE_PRIVATE): New macros. * src/cff/cfftoken.h: Add fields for CFF2 dictionaries (but no blend stuff). * src/cff/cfftypes.h (CFF_Index): Add `hdr_size' field. (CFF_FontRecDict): Add `maxstack' field. (CFF_Private): Add `subfont' field. (CFF_Font): Add `top_dict_length' and `cff2' fields. * src/sfnt/sfobjs.c (sfnt_load_face): Handle `CFF2' table.
This commit is contained in:
parent
3bd79cc257
commit
9f62d2ca06
52
ChangeLog
52
ChangeLog
|
@ -1,3 +1,55 @@
|
||||||
|
2016-12-15 Dave Arnold <darnold@adobe.com>
|
||||||
|
Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
|
[cff] Implement CFF2 support (1/2).
|
||||||
|
|
||||||
|
This commit does not contain the blend code for font variation
|
||||||
|
support, which follows in another commit.
|
||||||
|
|
||||||
|
You should ignore whitespace while inspecting this commit.
|
||||||
|
|
||||||
|
* include/freetype/internal/tttypes.h (TT_Face): Add `isCFF2'
|
||||||
|
member.
|
||||||
|
|
||||||
|
* src/cff/cf2font.h (CF2_Font): Add `isCFF2' member.
|
||||||
|
|
||||||
|
* src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Handle `isCFF2'
|
||||||
|
flag.
|
||||||
|
(cf2_getMaxstack): New function.
|
||||||
|
* src/cff/cf2ft.h: Updated.
|
||||||
|
|
||||||
|
* src/cff/cf2intrp.c (cf2_escRESERVED_38): New enum.
|
||||||
|
(cf2_interpT2CharString): Handle CFF2 differences.
|
||||||
|
Add tracing message for errors.
|
||||||
|
|
||||||
|
* src/cff/cffdrivr.c (cff_get_glyph_name, cff_get_name_index):
|
||||||
|
Update for CFF2.
|
||||||
|
|
||||||
|
* src/cff/cffload.c (FT_FIXED_ONE): New macro.
|
||||||
|
(cff_index_init, cff_index_load_offsets, cff_index_access_element,
|
||||||
|
cff_index_get_name, cff_ft_select_get, cff_load_private_dict,
|
||||||
|
cff_subfont_load, cff_font_load): Handle CFF2.
|
||||||
|
* src/cff/cffload.h: Updated.
|
||||||
|
|
||||||
|
* src/cff/cffobjs.c (cff_face_init): Handle CFF2.
|
||||||
|
|
||||||
|
* src/cff/cffparse.c (cff_parse_maxstack): New function.
|
||||||
|
(CFFCODE_TOPDICT, CFFCODE_PRIVATE): Removed
|
||||||
|
* src/cff/cffparse.h (CFF2_MAX_STACK, CFF2_DEFAULT_STACK): New
|
||||||
|
macros.
|
||||||
|
(CFF2_CODE_TOPDICT, CFF2_CODE_FONTDICT, CFF2_CODE_PRIVATE): New
|
||||||
|
macros.
|
||||||
|
|
||||||
|
* src/cff/cfftoken.h: Add fields for CFF2 dictionaries (but no blend
|
||||||
|
stuff).
|
||||||
|
|
||||||
|
* src/cff/cfftypes.h (CFF_Index): Add `hdr_size' field.
|
||||||
|
(CFF_FontRecDict): Add `maxstack' field.
|
||||||
|
(CFF_Private): Add `subfont' field.
|
||||||
|
(CFF_Font): Add `top_dict_length' and `cff2' fields.
|
||||||
|
|
||||||
|
* src/sfnt/sfobjs.c (sfnt_load_face): Handle `CFF2' table.
|
||||||
|
|
||||||
2016-12-15 Werner Lemberg <wl@gnu.org>
|
2016-12-15 Werner Lemberg <wl@gnu.org>
|
||||||
Dave Arnold <darnold@adobe.com>
|
Dave Arnold <darnold@adobe.com>
|
||||||
|
|
||||||
|
|
|
@ -1419,6 +1419,8 @@ FT_BEGIN_HEADER
|
||||||
FT_ULong glyf_len;
|
FT_ULong glyf_len;
|
||||||
FT_ULong glyf_offset; /* since 2.7.1 */
|
FT_ULong glyf_offset; /* since 2.7.1 */
|
||||||
|
|
||||||
|
FT_Bool isCFF2; /* since 2.7.1 */
|
||||||
|
|
||||||
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
|
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
|
||||||
FT_Bool doblend;
|
FT_Bool doblend;
|
||||||
GX_Blend blend;
|
GX_Blend blend;
|
||||||
|
|
|
@ -234,7 +234,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* set up values for the current FontDict and matrix */
|
/* set up values for the current FontDict and matrix; */
|
||||||
|
/* called for each glyph to be rendered */
|
||||||
|
|
||||||
/* caller's transform is adjusted for subpixel positioning */
|
/* caller's transform is adjusted for subpixel positioning */
|
||||||
static void
|
static void
|
||||||
|
@ -423,7 +424,8 @@
|
||||||
|
|
||||||
/* compute blue zones for this instance */
|
/* compute blue zones for this instance */
|
||||||
cf2_blues_init( &font->blues, font );
|
cf2_blues_init( &font->blues, font );
|
||||||
}
|
|
||||||
|
} /* needExtraSetup */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ FT_BEGIN_HEADER
|
||||||
FT_Memory memory;
|
FT_Memory memory;
|
||||||
FT_Error error; /* shared error for this instance */
|
FT_Error error; /* shared error for this instance */
|
||||||
|
|
||||||
|
FT_Bool isCFF2;
|
||||||
CF2_RenderingFlags renderingFlags;
|
CF2_RenderingFlags renderingFlags;
|
||||||
|
|
||||||
/* variables that depend on Transform: */
|
/* variables that depend on Transform: */
|
||||||
|
|
|
@ -366,6 +366,9 @@
|
||||||
&hinted,
|
&hinted,
|
||||||
&scaled );
|
&scaled );
|
||||||
|
|
||||||
|
/* copy isCFF2 boolean from TT_Face to CF2_Font */
|
||||||
|
font->isCFF2 = builder->face->isCFF2;
|
||||||
|
|
||||||
font->renderingFlags = 0;
|
font->renderingFlags = 0;
|
||||||
if ( hinted )
|
if ( hinted )
|
||||||
font->renderingFlags |= CF2_FlagsHinted;
|
font->renderingFlags |= CF2_FlagsHinted;
|
||||||
|
@ -413,6 +416,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* get maxstack value from CFF2 Top DICT */
|
||||||
|
FT_LOCAL_DEF( FT_UInt )
|
||||||
|
cf2_getMaxstack( CFF_Decoder* decoder )
|
||||||
|
{
|
||||||
|
FT_ASSERT( decoder && decoder->cff );
|
||||||
|
|
||||||
|
return decoder->cff->top_font.font_dict.maxstack;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* get `y_ppem' from `CFF_Size' */
|
/* get `y_ppem' from `CFF_Size' */
|
||||||
FT_LOCAL_DEF( CF2_Fixed )
|
FT_LOCAL_DEF( CF2_Fixed )
|
||||||
cf2_getPpemY( CFF_Decoder* decoder )
|
cf2_getPpemY( CFF_Decoder* decoder )
|
||||||
|
|
|
@ -65,6 +65,10 @@ FT_BEGIN_HEADER
|
||||||
cf2_getSubfont( CFF_Decoder* decoder );
|
cf2_getSubfont( CFF_Decoder* decoder );
|
||||||
|
|
||||||
|
|
||||||
|
FT_LOCAL( FT_UInt )
|
||||||
|
cf2_getMaxstack( CFF_Decoder* decoder );
|
||||||
|
|
||||||
|
|
||||||
FT_LOCAL( CF2_Fixed )
|
FT_LOCAL( CF2_Fixed )
|
||||||
cf2_getPpemY( CFF_Decoder* decoder );
|
cf2_getPpemY( CFF_Decoder* decoder );
|
||||||
FT_LOCAL( CF2_Fixed )
|
FT_LOCAL( CF2_Fixed )
|
||||||
|
|
|
@ -273,7 +273,8 @@
|
||||||
cf2_escHFLEX, /* 34 */
|
cf2_escHFLEX, /* 34 */
|
||||||
cf2_escFLEX, /* 35 */
|
cf2_escFLEX, /* 35 */
|
||||||
cf2_escHFLEX1, /* 36 */
|
cf2_escHFLEX1, /* 36 */
|
||||||
cf2_escFLEX1 /* 37 */
|
cf2_escFLEX1, /* 37 */
|
||||||
|
cf2_escRESERVED_38 /* 38 & all higher */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -445,6 +446,7 @@
|
||||||
CF2_Fixed hintOriginY = curY;
|
CF2_Fixed hintOriginY = curY;
|
||||||
|
|
||||||
CF2_Stack opStack = NULL;
|
CF2_Stack opStack = NULL;
|
||||||
|
FT_UInt stackSize;
|
||||||
FT_Byte op1; /* first opcode byte */
|
FT_Byte op1; /* first opcode byte */
|
||||||
|
|
||||||
CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */
|
CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */
|
||||||
|
@ -520,19 +522,24 @@
|
||||||
* If one of the above operators occurs without explicitly specifying
|
* If one of the above operators occurs without explicitly specifying
|
||||||
* a width, we assume the default width.
|
* a width, we assume the default width.
|
||||||
*
|
*
|
||||||
|
* CFF2 charstrings always return the default width (0).
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
haveWidth = FALSE;
|
haveWidth = font->isCFF2 ? TRUE : FALSE;
|
||||||
*width = cf2_getDefaultWidthX( decoder );
|
*width = cf2_getDefaultWidthX( decoder );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: at this point, all pointers to resources must be NULL
|
* Note: At this point, all pointers to resources must be NULL
|
||||||
* and all local objects must be initialized.
|
* and all local objects must be initialized.
|
||||||
* There must be no branches to exit: above this point.
|
* There must be no branches to `exit:' above this point.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* allocate an operand stack */
|
/* allocate an operand stack */
|
||||||
opStack = cf2_stack_init( memory, error, CF2_OPERAND_STACK_SIZE );
|
stackSize = font->isCFF2 ? cf2_getMaxstack( decoder )
|
||||||
|
: CF2_OPERAND_STACK_SIZE;
|
||||||
|
opStack = cf2_stack_init( memory, error, stackSize );
|
||||||
|
|
||||||
if ( !opStack )
|
if ( !opStack )
|
||||||
{
|
{
|
||||||
lastError = FT_THROW( Out_Of_Memory );
|
lastError = FT_THROW( Out_Of_Memory );
|
||||||
|
@ -561,14 +568,23 @@
|
||||||
{
|
{
|
||||||
/* If we've reached the end of the charstring, simulate a */
|
/* If we've reached the end of the charstring, simulate a */
|
||||||
/* cf2_cmdRETURN or cf2_cmdENDCHAR. */
|
/* cf2_cmdRETURN or cf2_cmdENDCHAR. */
|
||||||
|
/* We do this for both CFF and CFF2. */
|
||||||
if ( charstringIndex )
|
if ( charstringIndex )
|
||||||
op1 = cf2_cmdRETURN; /* end of buffer for subroutine */
|
op1 = cf2_cmdRETURN; /* end of buffer for subroutine */
|
||||||
else
|
else
|
||||||
op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
|
op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
op1 = (FT_Byte)cf2_buf_readByte( charstring );
|
op1 = (FT_Byte)cf2_buf_readByte( charstring );
|
||||||
|
|
||||||
|
/* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */
|
||||||
|
/* Note: Trace message will report 0 instead of 11 or 14. */
|
||||||
|
if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) &&
|
||||||
|
font->isCFF2 )
|
||||||
|
op1 = cf2_cmdRESERVED_0;
|
||||||
|
}
|
||||||
|
|
||||||
/* check for errors once per loop */
|
/* check for errors once per loop */
|
||||||
if ( *error )
|
if ( *error )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -830,6 +846,8 @@
|
||||||
FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring );
|
FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring );
|
||||||
|
|
||||||
|
|
||||||
|
/* first switch for 2-byte operators handles CFF2 */
|
||||||
|
/* and opcodes that are reserved for both CFF and CFF2 */
|
||||||
switch ( op2 )
|
switch ( op2 )
|
||||||
{
|
{
|
||||||
case cf2_escHFLEX:
|
case cf2_escHFLEX:
|
||||||
|
@ -928,6 +946,7 @@
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* these opcodes are reserved in both CFF & CFF2 */
|
||||||
case cf2_escRESERVED_1:
|
case cf2_escRESERVED_1:
|
||||||
case cf2_escRESERVED_2:
|
case cf2_escRESERVED_2:
|
||||||
case cf2_escRESERVED_6:
|
case cf2_escRESERVED_6:
|
||||||
|
@ -944,329 +963,339 @@
|
||||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cf2_escDOTSECTION:
|
|
||||||
/* something about `flip type of locking' -- ignore it */
|
|
||||||
FT_TRACE4(( " dotsection\n" ));
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cf2_escAND:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg1;
|
|
||||||
CF2_F16Dot16 arg2;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " and\n" ));
|
|
||||||
|
|
||||||
arg2 = cf2_stack_popFixed( opStack );
|
|
||||||
arg1 = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushInt( opStack, arg1 && arg2 );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escOR:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg1;
|
|
||||||
CF2_F16Dot16 arg2;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " or\n" ));
|
|
||||||
|
|
||||||
arg2 = cf2_stack_popFixed( opStack );
|
|
||||||
arg1 = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushInt( opStack, arg1 || arg2 );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escNOT:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " not\n" ));
|
|
||||||
|
|
||||||
arg = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushInt( opStack, !arg );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escABS:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " abs\n" ));
|
|
||||||
|
|
||||||
arg = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escADD:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 summand1;
|
|
||||||
CF2_F16Dot16 summand2;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " add\n" ));
|
|
||||||
|
|
||||||
summand2 = cf2_stack_popFixed( opStack );
|
|
||||||
summand1 = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, summand1 + summand2 );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escSUB:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 minuend;
|
|
||||||
CF2_F16Dot16 subtrahend;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " sub\n" ));
|
|
||||||
|
|
||||||
subtrahend = cf2_stack_popFixed( opStack );
|
|
||||||
minuend = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, minuend - subtrahend );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escDIV:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 dividend;
|
|
||||||
CF2_F16Dot16 divisor;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " div\n" ));
|
|
||||||
|
|
||||||
divisor = cf2_stack_popFixed( opStack );
|
|
||||||
dividend = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, FT_DivFix( dividend, divisor ) );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escNEG:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " neg\n" ));
|
|
||||||
|
|
||||||
arg = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, -arg );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escEQ:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg1;
|
|
||||||
CF2_F16Dot16 arg2;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " eq\n" ));
|
|
||||||
|
|
||||||
arg2 = cf2_stack_popFixed( opStack );
|
|
||||||
arg1 = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushInt( opStack, arg1 == arg2 );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escDROP:
|
|
||||||
FT_TRACE4(( " drop\n" ));
|
|
||||||
|
|
||||||
(void)cf2_stack_popFixed( opStack );
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escPUT:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 val;
|
|
||||||
CF2_Int idx;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " put\n" ));
|
|
||||||
|
|
||||||
idx = cf2_stack_popInt( opStack );
|
|
||||||
val = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
|
|
||||||
storage[idx] = val;
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escGET:
|
|
||||||
{
|
|
||||||
CF2_Int idx;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " get\n" ));
|
|
||||||
|
|
||||||
idx = cf2_stack_popInt( opStack );
|
|
||||||
|
|
||||||
if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
|
|
||||||
cf2_stack_pushFixed( opStack, storage[idx] );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escIFELSE:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg1;
|
|
||||||
CF2_F16Dot16 arg2;
|
|
||||||
CF2_F16Dot16 cond1;
|
|
||||||
CF2_F16Dot16 cond2;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " ifelse\n" ));
|
|
||||||
|
|
||||||
cond2 = cf2_stack_popFixed( opStack );
|
|
||||||
cond1 = cf2_stack_popFixed( opStack );
|
|
||||||
arg2 = cf2_stack_popFixed( opStack );
|
|
||||||
arg1 = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, cond1 <= cond2 ? arg1 : arg2 );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escRANDOM: /* in spec */
|
|
||||||
FT_TRACE4(( " random\n" ));
|
|
||||||
|
|
||||||
CF2_FIXME;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cf2_escMUL:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 factor1;
|
|
||||||
CF2_F16Dot16 factor2;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " mul\n" ));
|
|
||||||
|
|
||||||
factor2 = cf2_stack_popFixed( opStack );
|
|
||||||
factor1 = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, FT_MulFix( factor1, factor2 ) );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escSQRT:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " sqrt\n" ));
|
|
||||||
|
|
||||||
arg = cf2_stack_popFixed( opStack );
|
|
||||||
if ( arg > 0 )
|
|
||||||
{
|
|
||||||
FT_Fixed root = arg;
|
|
||||||
FT_Fixed new_root;
|
|
||||||
|
|
||||||
|
|
||||||
/* Babylonian method */
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
|
|
||||||
if ( new_root == root )
|
|
||||||
break;
|
|
||||||
root = new_root;
|
|
||||||
}
|
|
||||||
arg = new_root;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
arg = 0;
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, arg );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escDUP:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " dup\n" ));
|
|
||||||
|
|
||||||
arg = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, arg );
|
|
||||||
cf2_stack_pushFixed( opStack, arg );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escEXCH:
|
|
||||||
{
|
|
||||||
CF2_F16Dot16 arg1;
|
|
||||||
CF2_F16Dot16 arg2;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " exch\n" ));
|
|
||||||
|
|
||||||
arg2 = cf2_stack_popFixed( opStack );
|
|
||||||
arg1 = cf2_stack_popFixed( opStack );
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack, arg2 );
|
|
||||||
cf2_stack_pushFixed( opStack, arg1 );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escINDEX:
|
|
||||||
{
|
|
||||||
CF2_Int idx;
|
|
||||||
CF2_UInt size;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " index\n" ));
|
|
||||||
|
|
||||||
idx = cf2_stack_popInt( opStack );
|
|
||||||
size = cf2_stack_count( opStack );
|
|
||||||
|
|
||||||
if ( size > 0 )
|
|
||||||
{
|
|
||||||
/* for `cf2_stack_getReal', index 0 is bottom of stack */
|
|
||||||
CF2_UInt gr_idx;
|
|
||||||
|
|
||||||
|
|
||||||
if ( idx < 0 )
|
|
||||||
gr_idx = size - 1;
|
|
||||||
else if ( (CF2_UInt)idx >= size )
|
|
||||||
gr_idx = 0;
|
|
||||||
else
|
|
||||||
gr_idx = size - 1 - (CF2_UInt)idx;
|
|
||||||
|
|
||||||
cf2_stack_pushFixed( opStack,
|
|
||||||
cf2_stack_getReal( opStack, gr_idx ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
case cf2_escROLL:
|
|
||||||
{
|
|
||||||
CF2_Int idx;
|
|
||||||
CF2_Int count;
|
|
||||||
|
|
||||||
|
|
||||||
FT_TRACE4(( " roll\n" ));
|
|
||||||
|
|
||||||
idx = cf2_stack_popInt( opStack );
|
|
||||||
count = cf2_stack_popInt( opStack );
|
|
||||||
|
|
||||||
cf2_stack_roll( opStack, count, idx );
|
|
||||||
}
|
|
||||||
continue; /* do not clear the stack */
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
{
|
||||||
|
if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 )
|
||||||
|
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* second switch for 2-byte operators handles just CFF */
|
||||||
|
switch ( op2 )
|
||||||
|
{
|
||||||
|
|
||||||
}; /* end of switch statement checking `op2' */
|
case cf2_escDOTSECTION:
|
||||||
|
/* something about `flip type of locking' -- ignore it */
|
||||||
|
FT_TRACE4(( " dotsection\n" ));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cf2_escAND:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg1;
|
||||||
|
CF2_F16Dot16 arg2;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " and\n" ));
|
||||||
|
|
||||||
|
arg2 = cf2_stack_popFixed( opStack );
|
||||||
|
arg1 = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushInt( opStack, arg1 && arg2 );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escOR:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg1;
|
||||||
|
CF2_F16Dot16 arg2;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " or\n" ));
|
||||||
|
|
||||||
|
arg2 = cf2_stack_popFixed( opStack );
|
||||||
|
arg1 = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushInt( opStack, arg1 || arg2 );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escNOT:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " not\n" ));
|
||||||
|
|
||||||
|
arg = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushInt( opStack, !arg );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escABS:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " abs\n" ));
|
||||||
|
|
||||||
|
arg = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escADD:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 summand1;
|
||||||
|
CF2_F16Dot16 summand2;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " add\n" ));
|
||||||
|
|
||||||
|
summand2 = cf2_stack_popFixed( opStack );
|
||||||
|
summand1 = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, summand1 + summand2 );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escSUB:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 minuend;
|
||||||
|
CF2_F16Dot16 subtrahend;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " sub\n" ));
|
||||||
|
|
||||||
|
subtrahend = cf2_stack_popFixed( opStack );
|
||||||
|
minuend = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, minuend - subtrahend );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escDIV:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 dividend;
|
||||||
|
CF2_F16Dot16 divisor;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " div\n" ));
|
||||||
|
|
||||||
|
divisor = cf2_stack_popFixed( opStack );
|
||||||
|
dividend = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, FT_DivFix( dividend, divisor ) );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escNEG:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " neg\n" ));
|
||||||
|
|
||||||
|
arg = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, -arg );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escEQ:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg1;
|
||||||
|
CF2_F16Dot16 arg2;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " eq\n" ));
|
||||||
|
|
||||||
|
arg2 = cf2_stack_popFixed( opStack );
|
||||||
|
arg1 = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushInt( opStack, arg1 == arg2 );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escDROP:
|
||||||
|
FT_TRACE4(( " drop\n" ));
|
||||||
|
|
||||||
|
(void)cf2_stack_popFixed( opStack );
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escPUT:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 val;
|
||||||
|
CF2_Int idx;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " put\n" ));
|
||||||
|
|
||||||
|
idx = cf2_stack_popInt( opStack );
|
||||||
|
val = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
|
||||||
|
storage[idx] = val;
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escGET:
|
||||||
|
{
|
||||||
|
CF2_Int idx;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " get\n" ));
|
||||||
|
|
||||||
|
idx = cf2_stack_popInt( opStack );
|
||||||
|
|
||||||
|
if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
|
||||||
|
cf2_stack_pushFixed( opStack, storage[idx] );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escIFELSE:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg1;
|
||||||
|
CF2_F16Dot16 arg2;
|
||||||
|
CF2_F16Dot16 cond1;
|
||||||
|
CF2_F16Dot16 cond2;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " ifelse\n" ));
|
||||||
|
|
||||||
|
cond2 = cf2_stack_popFixed( opStack );
|
||||||
|
cond1 = cf2_stack_popFixed( opStack );
|
||||||
|
arg2 = cf2_stack_popFixed( opStack );
|
||||||
|
arg1 = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, cond1 <= cond2 ? arg1 : arg2 );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escRANDOM: /* in spec */
|
||||||
|
FT_TRACE4(( " random\n" ));
|
||||||
|
|
||||||
|
CF2_FIXME;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cf2_escMUL:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 factor1;
|
||||||
|
CF2_F16Dot16 factor2;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " mul\n" ));
|
||||||
|
|
||||||
|
factor2 = cf2_stack_popFixed( opStack );
|
||||||
|
factor1 = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, FT_MulFix( factor1, factor2 ) );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escSQRT:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " sqrt\n" ));
|
||||||
|
|
||||||
|
arg = cf2_stack_popFixed( opStack );
|
||||||
|
if ( arg > 0 )
|
||||||
|
{
|
||||||
|
FT_Fixed root = arg;
|
||||||
|
FT_Fixed new_root;
|
||||||
|
|
||||||
|
|
||||||
|
/* Babylonian method */
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
|
||||||
|
if ( new_root == root )
|
||||||
|
break;
|
||||||
|
root = new_root;
|
||||||
|
}
|
||||||
|
arg = new_root;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
arg = 0;
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, arg );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escDUP:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " dup\n" ));
|
||||||
|
|
||||||
|
arg = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, arg );
|
||||||
|
cf2_stack_pushFixed( opStack, arg );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escEXCH:
|
||||||
|
{
|
||||||
|
CF2_F16Dot16 arg1;
|
||||||
|
CF2_F16Dot16 arg2;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " exch\n" ));
|
||||||
|
|
||||||
|
arg2 = cf2_stack_popFixed( opStack );
|
||||||
|
arg1 = cf2_stack_popFixed( opStack );
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack, arg2 );
|
||||||
|
cf2_stack_pushFixed( opStack, arg1 );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escINDEX:
|
||||||
|
{
|
||||||
|
CF2_Int idx;
|
||||||
|
CF2_UInt size;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " index\n" ));
|
||||||
|
|
||||||
|
idx = cf2_stack_popInt( opStack );
|
||||||
|
size = cf2_stack_count( opStack );
|
||||||
|
|
||||||
|
if ( size > 0 )
|
||||||
|
{
|
||||||
|
/* for `cf2_stack_getReal', index 0 is bottom of stack */
|
||||||
|
CF2_UInt gr_idx;
|
||||||
|
|
||||||
|
|
||||||
|
if ( idx < 0 )
|
||||||
|
gr_idx = size - 1;
|
||||||
|
else if ( (CF2_UInt)idx >= size )
|
||||||
|
gr_idx = 0;
|
||||||
|
else
|
||||||
|
gr_idx = size - 1 - (CF2_UInt)idx;
|
||||||
|
|
||||||
|
cf2_stack_pushFixed( opStack,
|
||||||
|
cf2_stack_getReal( opStack, gr_idx ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
case cf2_escROLL:
|
||||||
|
{
|
||||||
|
CF2_Int idx;
|
||||||
|
CF2_Int count;
|
||||||
|
|
||||||
|
|
||||||
|
FT_TRACE4(( " roll\n" ));
|
||||||
|
|
||||||
|
idx = cf2_stack_popInt( opStack );
|
||||||
|
count = cf2_stack_popInt( opStack );
|
||||||
|
|
||||||
|
cf2_stack_roll( opStack, count, idx );
|
||||||
|
}
|
||||||
|
continue; /* do not clear the stack */
|
||||||
|
|
||||||
|
} /* end of 2nd switch checking op2 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* end of 1st switch checking op2 */
|
||||||
} /* case cf2_cmdESC */
|
} /* case cf2_cmdESC */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cf2_cmdENDCHAR:
|
case cf2_cmdENDCHAR:
|
||||||
|
@ -1288,7 +1317,8 @@
|
||||||
/* close path if still open */
|
/* close path if still open */
|
||||||
cf2_glyphpath_closeOpenPath( &glyphPath );
|
cf2_glyphpath_closeOpenPath( &glyphPath );
|
||||||
|
|
||||||
if ( cf2_stack_count( opStack ) > 1 )
|
/* disable seac for CFF2 (charstring ending with args on stack) */
|
||||||
|
if ( !font->isCFF2 && cf2_stack_count( opStack ) > 1 )
|
||||||
{
|
{
|
||||||
/* must be either 4 or 5 -- */
|
/* must be either 4 or 5 -- */
|
||||||
/* this is a (deprecated) implied `seac' operator */
|
/* this is a (deprecated) implied `seac' operator */
|
||||||
|
@ -1760,6 +1790,9 @@
|
||||||
/* check whether last error seen is also the first one */
|
/* check whether last error seen is also the first one */
|
||||||
cf2_setError( error, lastError );
|
cf2_setError( error, lastError );
|
||||||
|
|
||||||
|
if ( *error )
|
||||||
|
FT_TRACE4(( "charstring error %d\n", *error ));
|
||||||
|
|
||||||
/* free resources from objects we've used */
|
/* free resources from objects we've used */
|
||||||
cf2_glyphpath_finalize( &glyphPath );
|
cf2_glyphpath_finalize( &glyphPath );
|
||||||
cf2_arrstack_finalize( &vStemHintArray );
|
cf2_arrstack_finalize( &vStemHintArray );
|
||||||
|
|
|
@ -295,6 +295,35 @@
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
|
|
||||||
|
|
||||||
|
/* CFF2 table does not have glyph names; */
|
||||||
|
/* we need to use `post' table method */
|
||||||
|
if ( font->version_major == 2 )
|
||||||
|
{
|
||||||
|
FT_Library library = FT_FACE_LIBRARY( face );
|
||||||
|
FT_Module sfnt_module = FT_Get_Module( library, "sfnt" );
|
||||||
|
FT_Service_GlyphDict service =
|
||||||
|
(FT_Service_GlyphDict)ft_module_get_service(
|
||||||
|
sfnt_module,
|
||||||
|
FT_SERVICE_ID_GLYPH_DICT,
|
||||||
|
0 );
|
||||||
|
|
||||||
|
|
||||||
|
if ( service && service->get_name )
|
||||||
|
return service->get_name( FT_FACE( face ),
|
||||||
|
glyph_index,
|
||||||
|
buffer,
|
||||||
|
buffer_max );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FT_ERROR(( "cff_get_glyph_name:"
|
||||||
|
" cannot get glyph name from a CFF2 font\n"
|
||||||
|
" "
|
||||||
|
" without the `PSNames' module\n" ));
|
||||||
|
error = FT_THROW( Missing_Module );
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( !font->psnames )
|
if ( !font->psnames )
|
||||||
{
|
{
|
||||||
FT_ERROR(( "cff_get_glyph_name:"
|
FT_ERROR(( "cff_get_glyph_name:"
|
||||||
|
@ -336,6 +365,31 @@
|
||||||
cff = (CFF_FontRec *)face->extra.data;
|
cff = (CFF_FontRec *)face->extra.data;
|
||||||
charset = &cff->charset;
|
charset = &cff->charset;
|
||||||
|
|
||||||
|
/* CFF2 table does not have glyph names; */
|
||||||
|
/* we need to use `post' table method */
|
||||||
|
if ( cff->version_major == 2 )
|
||||||
|
{
|
||||||
|
FT_Library library = FT_FACE_LIBRARY( face );
|
||||||
|
FT_Module sfnt_module = FT_Get_Module( library, "sfnt" );
|
||||||
|
FT_Service_GlyphDict service =
|
||||||
|
(FT_Service_GlyphDict)ft_module_get_service(
|
||||||
|
sfnt_module,
|
||||||
|
FT_SERVICE_ID_GLYPH_DICT,
|
||||||
|
0 );
|
||||||
|
|
||||||
|
|
||||||
|
if ( service && service->name_index )
|
||||||
|
return service->name_index( FT_FACE( face ), glyph_name );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FT_ERROR(( "cff_get_name_index:"
|
||||||
|
" cannot get glyph index from a CFF2 font\n"
|
||||||
|
" "
|
||||||
|
" without the `PSNames' module\n" ));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
|
FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
|
||||||
if ( !psnames )
|
if ( !psnames )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
#include "cfferrs.h"
|
#include "cfferrs.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define FT_FIXED_ONE ( (FT_Fixed)0x10000 )
|
||||||
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
||||||
static const FT_UShort cff_isoadobe_charset[229] =
|
static const FT_UShort cff_isoadobe_charset[229] =
|
||||||
|
@ -225,19 +228,33 @@
|
||||||
static FT_Error
|
static FT_Error
|
||||||
cff_index_init( CFF_Index idx,
|
cff_index_init( CFF_Index idx,
|
||||||
FT_Stream stream,
|
FT_Stream stream,
|
||||||
FT_Bool load )
|
FT_Bool load,
|
||||||
|
FT_Bool cff2 )
|
||||||
{
|
{
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_Memory memory = stream->memory;
|
FT_Memory memory = stream->memory;
|
||||||
FT_UShort count;
|
FT_UInt count;
|
||||||
|
|
||||||
|
|
||||||
FT_ZERO( idx );
|
FT_ZERO( idx );
|
||||||
|
|
||||||
idx->stream = stream;
|
idx->stream = stream;
|
||||||
idx->start = FT_STREAM_POS();
|
idx->start = FT_STREAM_POS();
|
||||||
if ( !FT_READ_USHORT( count ) &&
|
|
||||||
count > 0 )
|
if ( cff2 )
|
||||||
|
{
|
||||||
|
if ( FT_READ_ULONG( count ) )
|
||||||
|
goto Exit;
|
||||||
|
idx->hdr_size = 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( FT_READ_USHORT( count ) )
|
||||||
|
goto Exit;
|
||||||
|
idx->hdr_size = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( count > 0 )
|
||||||
{
|
{
|
||||||
FT_Byte offsize;
|
FT_Byte offsize;
|
||||||
FT_ULong size;
|
FT_ULong size;
|
||||||
|
@ -258,7 +275,7 @@
|
||||||
idx->off_size = offsize;
|
idx->off_size = offsize;
|
||||||
size = (FT_ULong)( count + 1 ) * offsize;
|
size = (FT_ULong)( count + 1 ) * offsize;
|
||||||
|
|
||||||
idx->data_offset = idx->start + 3 + size;
|
idx->data_offset = idx->start + idx->hdr_size + size;
|
||||||
|
|
||||||
if ( FT_STREAM_SKIP( size - offsize ) )
|
if ( FT_STREAM_SKIP( size - offsize ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
@ -335,7 +352,7 @@
|
||||||
data_size = (FT_ULong)( idx->count + 1 ) * offsize;
|
data_size = (FT_ULong)( idx->count + 1 ) * offsize;
|
||||||
|
|
||||||
if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
|
if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
|
||||||
FT_STREAM_SEEK( idx->start + 3 ) ||
|
FT_STREAM_SEEK( idx->start + idx->hdr_size ) ||
|
||||||
FT_FRAME_ENTER( data_size ) )
|
FT_FRAME_ENTER( data_size ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
@ -493,7 +510,7 @@
|
||||||
FT_ULong pos = element * idx->off_size;
|
FT_ULong pos = element * idx->off_size;
|
||||||
|
|
||||||
|
|
||||||
if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
|
if ( FT_STREAM_SEEK( idx->start + idx->hdr_size + pos ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
off1 = cff_index_read_offset( idx, &error );
|
off1 = cff_index_read_offset( idx, &error );
|
||||||
|
@ -589,13 +606,18 @@
|
||||||
FT_UInt element )
|
FT_UInt element )
|
||||||
{
|
{
|
||||||
CFF_Index idx = &font->name_index;
|
CFF_Index idx = &font->name_index;
|
||||||
FT_Memory memory = idx->stream->memory;
|
FT_Memory memory;
|
||||||
FT_Byte* bytes;
|
FT_Byte* bytes;
|
||||||
FT_ULong byte_len;
|
FT_ULong byte_len;
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_String* name = 0;
|
FT_String* name = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if ( !idx->stream ) /* CFF2 does not include a name index */
|
||||||
|
goto Exit;
|
||||||
|
|
||||||
|
memory = idx->stream->memory;
|
||||||
|
|
||||||
error = cff_index_access_element( idx, element, &bytes, &byte_len );
|
error = cff_index_access_element( idx, element, &bytes, &byte_len );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
@ -724,6 +746,10 @@
|
||||||
{
|
{
|
||||||
FT_Byte fd = 0;
|
FT_Byte fd = 0;
|
||||||
|
|
||||||
|
/* if there is no FDSelect, return zero */
|
||||||
|
/* Note: CFF2 with just one Font Dict has no FDSelect */
|
||||||
|
if ( fdselect->data == NULL )
|
||||||
|
goto Exit;
|
||||||
|
|
||||||
switch ( fdselect->format )
|
switch ( fdselect->format )
|
||||||
{
|
{
|
||||||
|
@ -777,6 +803,7 @@
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Exit:
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1356,10 +1383,13 @@
|
||||||
priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
|
priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
|
||||||
priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
|
priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
|
||||||
|
|
||||||
stackSize = CFF_MAX_STACK_DEPTH + 1;
|
priv->subfont = subfont;
|
||||||
|
|
||||||
|
stackSize = font->cff2 ? font->top_font.font_dict.maxstack
|
||||||
|
: CFF_MAX_STACK_DEPTH + 1;
|
||||||
|
|
||||||
if ( cff_parser_init( &parser,
|
if ( cff_parser_init( &parser,
|
||||||
CFF_CODE_PRIVATE,
|
font->cff2 ? CFF2_CODE_PRIVATE : CFF_CODE_PRIVATE,
|
||||||
priv,
|
priv,
|
||||||
font->library,
|
font->library,
|
||||||
stackSize,
|
stackSize,
|
||||||
|
@ -1393,12 +1423,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* There are 3 ways to call this function, distinguished by code. */
|
||||||
|
/* */
|
||||||
|
/* . CFF_CODE_TOPDICT for either a CFF Top DICT or a CFF Font DICT */
|
||||||
|
/* . CFF2_CODE_TOPDICT for CFF2 Top DICT */
|
||||||
|
/* . CFF2_CODE_FONTDICT for CFF2 Font DICT */
|
||||||
|
|
||||||
static FT_Error
|
static FT_Error
|
||||||
cff_subfont_load( CFF_SubFont subfont,
|
cff_subfont_load( CFF_SubFont subfont,
|
||||||
CFF_Index idx,
|
CFF_Index idx,
|
||||||
FT_UInt font_index,
|
FT_UInt font_index,
|
||||||
FT_Stream stream,
|
FT_Stream stream,
|
||||||
FT_ULong base_offset,
|
FT_ULong base_offset,
|
||||||
|
FT_UInt code,
|
||||||
CFF_Font font )
|
CFF_Font font )
|
||||||
{
|
{
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
|
@ -1408,11 +1445,16 @@
|
||||||
CFF_FontRecDict top = &subfont->font_dict;
|
CFF_FontRecDict top = &subfont->font_dict;
|
||||||
CFF_Private priv = &subfont->private_dict;
|
CFF_Private priv = &subfont->private_dict;
|
||||||
|
|
||||||
FT_UInt stackSize = CFF_MAX_STACK_DEPTH;
|
FT_Bool cff2 = ( code == CFF2_CODE_TOPDICT ||
|
||||||
|
code == CFF2_CODE_FONTDICT );
|
||||||
|
FT_UInt stackSize = cff2 ? CFF2_DEFAULT_STACK
|
||||||
|
: CFF_MAX_STACK_DEPTH;
|
||||||
|
|
||||||
|
|
||||||
|
/* Note: We use default stack size for CFF2 Font DICT because */
|
||||||
|
/* Top and Font DICTs are not allowed to have blend operators. */
|
||||||
if ( cff_parser_init( &parser,
|
if ( cff_parser_init( &parser,
|
||||||
CFF_CODE_TOPDICT,
|
code,
|
||||||
&subfont->font_dict,
|
&subfont->font_dict,
|
||||||
font->library,
|
font->library,
|
||||||
stackSize,
|
stackSize,
|
||||||
|
@ -1444,14 +1486,35 @@
|
||||||
top->cid_ordering = 0xFFFFU;
|
top->cid_ordering = 0xFFFFU;
|
||||||
top->cid_font_name = 0xFFFFU;
|
top->cid_font_name = 0xFFFFU;
|
||||||
|
|
||||||
error = cff_index_access_element( idx, font_index, &dict, &dict_len );
|
/* set default stack size */
|
||||||
|
top->maxstack = cff2 ? CFF2_DEFAULT_STACK : 48;
|
||||||
|
|
||||||
|
if ( idx->count ) /* count is nonzero for a real index */
|
||||||
|
error = cff_index_access_element( idx, font_index, &dict, &dict_len );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* CFF2 has a fake top dict index; */
|
||||||
|
/* simulate `cff_index_access_element' */
|
||||||
|
|
||||||
|
/* Note: macros implicitly use `stream' and set `error' */
|
||||||
|
if ( FT_STREAM_SEEK( idx->data_offset ) ||
|
||||||
|
FT_FRAME_EXTRACT( idx->data_size, dict ) )
|
||||||
|
goto Exit;
|
||||||
|
|
||||||
|
dict_len = idx->data_size;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !error )
|
if ( !error )
|
||||||
{
|
{
|
||||||
FT_TRACE4(( " top dictionary:\n" ));
|
FT_TRACE4(( " top dictionary:\n" ));
|
||||||
error = cff_parser_run( &parser, dict, dict + dict_len );
|
error = cff_parser_run( &parser, dict, dict + dict_len );
|
||||||
}
|
}
|
||||||
|
|
||||||
cff_index_forget_element( idx, &dict );
|
/* clean up regardless of error */
|
||||||
|
if ( idx->count )
|
||||||
|
cff_index_forget_element( idx, &dict );
|
||||||
|
else
|
||||||
|
FT_FRAME_RELEASE( dict );
|
||||||
|
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
@ -1460,7 +1523,11 @@
|
||||||
if ( top->cid_registry != 0xFFFFU )
|
if ( top->cid_registry != 0xFFFFU )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
/* parse the private dictionary, if any */
|
/* Parse the private dictionary, if any. */
|
||||||
|
/* */
|
||||||
|
/* CFF2 does not have a private dictionary in the Top DICT */
|
||||||
|
/* but may have one in a Font DICT. We need to parse */
|
||||||
|
/* the latter here in order to load any local subrs. */
|
||||||
error = cff_load_private_dict( font, subfont );
|
error = cff_load_private_dict( font, subfont );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
@ -1472,7 +1539,7 @@
|
||||||
priv->local_subrs_offset ) )
|
priv->local_subrs_offset ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
error = cff_index_init( &subfont->local_subrs_index, stream, 1 );
|
error = cff_index_init( &subfont->local_subrs_index, stream, 1, cff2 );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
@ -1506,18 +1573,18 @@
|
||||||
FT_Stream stream,
|
FT_Stream stream,
|
||||||
FT_Int face_index,
|
FT_Int face_index,
|
||||||
CFF_Font font,
|
CFF_Font font,
|
||||||
FT_Bool pure_cff )
|
FT_Bool pure_cff,
|
||||||
|
FT_Bool cff2 )
|
||||||
{
|
{
|
||||||
static const FT_Frame_Field cff_header_fields[] =
|
static const FT_Frame_Field cff_header_fields[] =
|
||||||
{
|
{
|
||||||
#undef FT_STRUCTURE
|
#undef FT_STRUCTURE
|
||||||
#define FT_STRUCTURE CFF_FontRec
|
#define FT_STRUCTURE CFF_FontRec
|
||||||
|
|
||||||
FT_FRAME_START( 4 ),
|
FT_FRAME_START( 3 ),
|
||||||
FT_FRAME_BYTE( version_major ),
|
FT_FRAME_BYTE( version_major ),
|
||||||
FT_FRAME_BYTE( version_minor ),
|
FT_FRAME_BYTE( version_minor ),
|
||||||
FT_FRAME_BYTE( header_size ),
|
FT_FRAME_BYTE( header_size ),
|
||||||
FT_FRAME_BYTE( absolute_offsize ),
|
|
||||||
FT_FRAME_END
|
FT_FRAME_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1538,40 +1605,80 @@
|
||||||
font->library = library;
|
font->library = library;
|
||||||
font->stream = stream;
|
font->stream = stream;
|
||||||
font->memory = memory;
|
font->memory = memory;
|
||||||
|
font->cff2 = cff2;
|
||||||
font->base_offset = base_offset;
|
font->base_offset = base_offset;
|
||||||
|
|
||||||
/* read CFF font header */
|
/* read CFF font header */
|
||||||
if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
|
if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
/* check format */
|
if ( cff2 )
|
||||||
if ( font->version_major != 1 ||
|
|
||||||
font->header_size < 4 ||
|
|
||||||
font->absolute_offsize > 4 )
|
|
||||||
{
|
{
|
||||||
FT_TRACE2(( " not a CFF font header\n" ));
|
if ( font->version_major != 2 ||
|
||||||
error = FT_THROW( Unknown_File_Format );
|
font->header_size < 5 )
|
||||||
goto Exit;
|
{
|
||||||
|
FT_TRACE2(( " not a CFF2 font header\n" ));
|
||||||
|
error = FT_THROW( Unknown_File_Format );
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( FT_READ_USHORT( font->top_dict_length ) )
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( font->version_major != 1 ||
|
||||||
|
font->header_size < 4 )
|
||||||
|
{
|
||||||
|
FT_TRACE2(( " not a CFF font header\n" ));
|
||||||
|
error = FT_THROW( Unknown_File_Format );
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skip the rest of the header */
|
/* skip the rest of the header */
|
||||||
if ( FT_STREAM_SKIP( font->header_size - 4 ) )
|
if ( FT_STREAM_SEEK( base_offset + font->header_size ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
/* read the name, top dict, string and global subrs index */
|
if ( cff2 )
|
||||||
if ( FT_SET_ERROR( cff_index_init( &font->name_index,
|
{
|
||||||
stream, 0 ) ) ||
|
/* For CFF2, the top dict data immediately follow the header */
|
||||||
FT_SET_ERROR( cff_index_init( &font->font_dict_index,
|
/* and the length is stored in the header `offSize' field; */
|
||||||
stream, 0 ) ) ||
|
/* there is no index for it. */
|
||||||
FT_SET_ERROR( cff_index_init( &string_index,
|
/* */
|
||||||
stream, 1 ) ) ||
|
/* Use the `font_dict_index' to save the current position */
|
||||||
FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
|
/* and length of data, but leave count at zero as an indicator. */
|
||||||
stream, 1 ) ) ||
|
FT_ZERO( &font->font_dict_index );
|
||||||
FT_SET_ERROR( cff_index_get_pointers( &string_index,
|
|
||||||
&font->strings,
|
font->font_dict_index.data_offset = FT_STREAM_POS();
|
||||||
&font->string_pool,
|
font->font_dict_index.data_size = font->top_dict_length;
|
||||||
&font->string_pool_size ) ) )
|
|
||||||
goto Exit;
|
/* skip the top dict data for now, we will parse it later */
|
||||||
|
if ( FT_STREAM_SKIP( font->top_dict_length ) )
|
||||||
|
goto Exit;
|
||||||
|
|
||||||
|
/* next, read the global subrs index */
|
||||||
|
if ( FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
|
||||||
|
stream, 1, cff2 ) ) )
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* for CFF, read the name, top dict, string and global subrs index */
|
||||||
|
if ( FT_SET_ERROR( cff_index_init( &font->name_index,
|
||||||
|
stream, 0, cff2 ) ) ||
|
||||||
|
FT_SET_ERROR( cff_index_init( &font->font_dict_index,
|
||||||
|
stream, 0, cff2 ) ) ||
|
||||||
|
FT_SET_ERROR( cff_index_init( &string_index,
|
||||||
|
stream, 1, cff2 ) ) ||
|
||||||
|
FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
|
||||||
|
stream, 1, cff2 ) ) ||
|
||||||
|
FT_SET_ERROR( cff_index_get_pointers( &string_index,
|
||||||
|
&font->strings,
|
||||||
|
&font->string_pool,
|
||||||
|
&font->string_pool_size ) ) )
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
font->num_strings = string_index.count;
|
font->num_strings = string_index.count;
|
||||||
|
|
||||||
|
@ -1617,6 +1724,7 @@
|
||||||
subfont_index,
|
subfont_index,
|
||||||
stream,
|
stream,
|
||||||
base_offset,
|
base_offset,
|
||||||
|
cff2 ? CFF2_CODE_TOPDICT : CFF_CODE_TOPDICT,
|
||||||
font );
|
font );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
@ -1624,12 +1732,13 @@
|
||||||
if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
|
if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
error = cff_index_init( &font->charstrings_index, stream, 0 );
|
error = cff_index_init( &font->charstrings_index, stream, 0, cff2 );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
/* now, check for a CID font */
|
/* now, check for a CID or CFF2 font */
|
||||||
if ( dict->cid_registry != 0xFFFFU )
|
if ( dict->cid_registry != 0xFFFFU ||
|
||||||
|
cff2 )
|
||||||
{
|
{
|
||||||
CFF_IndexRec fd_index;
|
CFF_IndexRec fd_index;
|
||||||
CFF_SubFont sub = NULL;
|
CFF_SubFont sub = NULL;
|
||||||
|
@ -1641,10 +1750,12 @@
|
||||||
if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
|
if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
error = cff_index_init( &fd_index, stream, 0 );
|
error = cff_index_init( &fd_index, stream, 0, cff2 );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
/* Font Dicts are not limited to 256 for CFF2. */
|
||||||
|
/* TODO: support this for CFF2 */
|
||||||
if ( fd_index.count > CFF_MAX_CID_FONTS )
|
if ( fd_index.count > CFF_MAX_CID_FONTS )
|
||||||
{
|
{
|
||||||
FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
|
FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
|
||||||
|
@ -1670,16 +1781,20 @@
|
||||||
idx,
|
idx,
|
||||||
stream,
|
stream,
|
||||||
base_offset,
|
base_offset,
|
||||||
|
cff2 ? CFF2_CODE_FONTDICT
|
||||||
|
: CFF_CODE_TOPDICT,
|
||||||
font );
|
font );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Fail_CID;
|
goto Fail_CID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now load the FD Select array */
|
/* now load the FD Select array; */
|
||||||
error = CFF_Load_FD_Select( &font->fd_select,
|
/* CFF2 omits FDSelect if there is only one FD */
|
||||||
font->charstrings_index.count,
|
if ( !cff2 || fd_index.count > 1 )
|
||||||
stream,
|
error = CFF_Load_FD_Select( &font->fd_select,
|
||||||
base_offset + dict->cid_fd_select_offset );
|
font->charstrings_index.count,
|
||||||
|
stream,
|
||||||
|
base_offset + dict->cid_fd_select_offset );
|
||||||
|
|
||||||
Fail_CID:
|
Fail_CID:
|
||||||
cff_index_done( &fd_index );
|
cff_index_done( &fd_index );
|
||||||
|
@ -1707,7 +1822,7 @@
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
/* read the Charset and Encoding tables if available */
|
/* read the Charset and Encoding tables if available */
|
||||||
if ( font->num_glyphs > 0 )
|
if ( !cff2 && font->num_glyphs > 0 )
|
||||||
{
|
{
|
||||||
FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
|
FT_Bool invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
|
||||||
|
|
||||||
|
@ -1755,7 +1870,7 @@
|
||||||
cff_index_done( &font->charstrings_index );
|
cff_index_done( &font->charstrings_index );
|
||||||
|
|
||||||
/* release font dictionaries, but only if working with */
|
/* release font dictionaries, but only if working with */
|
||||||
/* a CID keyed CFF font */
|
/* a CID keyed CFF font or a CFF2 font */
|
||||||
if ( font->num_subfonts > 0 )
|
if ( font->num_subfonts > 0 )
|
||||||
{
|
{
|
||||||
for ( idx = 0; idx < font->num_subfonts; idx++ )
|
for ( idx = 0; idx < font->num_subfonts; idx++ )
|
||||||
|
|
|
@ -60,11 +60,12 @@ FT_BEGIN_HEADER
|
||||||
|
|
||||||
|
|
||||||
FT_LOCAL( FT_Error )
|
FT_LOCAL( FT_Error )
|
||||||
cff_font_load( FT_Library library,
|
cff_font_load( FT_Library library,
|
||||||
FT_Stream stream,
|
FT_Stream stream,
|
||||||
FT_Int face_index,
|
FT_Int face_index,
|
||||||
CFF_Font font,
|
CFF_Font font,
|
||||||
FT_Bool pure_cff );
|
FT_Bool pure_cff,
|
||||||
|
FT_Bool cff2 );
|
||||||
|
|
||||||
FT_LOCAL( void )
|
FT_LOCAL( void )
|
||||||
cff_font_done( CFF_Font font );
|
cff_font_done( CFF_Font font );
|
||||||
|
|
|
@ -491,6 +491,7 @@
|
||||||
FT_Service_PsCMaps psnames;
|
FT_Service_PsCMaps psnames;
|
||||||
PSHinter_Service pshinter;
|
PSHinter_Service pshinter;
|
||||||
FT_Bool pure_cff = 1;
|
FT_Bool pure_cff = 1;
|
||||||
|
FT_Bool cff2 = 0;
|
||||||
FT_Bool sfnt_format = 0;
|
FT_Bool sfnt_format = 0;
|
||||||
FT_Library library = cffface->driver->root.library;
|
FT_Library library = cffface->driver->root.library;
|
||||||
|
|
||||||
|
@ -553,8 +554,18 @@
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now load the CFF part of the file */
|
/* now load the CFF part of the file; */
|
||||||
error = face->goto_table( face, TTAG_CFF, stream, 0 );
|
/* give priority to CFF2 */
|
||||||
|
error = face->goto_table( face, TTAG_CFF2, stream, 0 );
|
||||||
|
if ( !error )
|
||||||
|
{
|
||||||
|
cff2 = 1;
|
||||||
|
face->isCFF2 = cff2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( FT_ERR_EQ( error, Table_Missing ) )
|
||||||
|
error = face->goto_table( face, TTAG_CFF, stream, 0 );
|
||||||
|
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
@ -579,7 +590,12 @@
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
face->extra.data = cff;
|
face->extra.data = cff;
|
||||||
error = cff_font_load( library, stream, face_index, cff, pure_cff );
|
error = cff_font_load( library,
|
||||||
|
stream,
|
||||||
|
face_index,
|
||||||
|
cff,
|
||||||
|
pure_cff,
|
||||||
|
cff2 );
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
|
|
@ -823,6 +823,35 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* maxstack operator increases parser and operand stacks for CFF2 */
|
||||||
|
static FT_Error
|
||||||
|
cff_parse_maxstack( CFF_Parser parser )
|
||||||
|
{
|
||||||
|
/* maxstack operator can only be used in a Top DICT */
|
||||||
|
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
|
||||||
|
FT_Byte** data = parser->stack;
|
||||||
|
FT_Error error = FT_Err_Ok;
|
||||||
|
|
||||||
|
|
||||||
|
if ( !dict )
|
||||||
|
{
|
||||||
|
error = FT_THROW( Invalid_File_Format );
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
dict->maxstack = (FT_UInt)cff_parse_num( parser, data++ );
|
||||||
|
if ( dict->maxstack > CFF2_MAX_STACK )
|
||||||
|
dict->maxstack = CFF2_MAX_STACK;
|
||||||
|
if ( dict->maxstack < CFF2_DEFAULT_STACK )
|
||||||
|
dict->maxstack = CFF2_DEFAULT_STACK;
|
||||||
|
|
||||||
|
FT_TRACE4(( " %d\n", dict->maxstack ));
|
||||||
|
|
||||||
|
Exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define CFF_FIELD_NUM( code, name, id ) \
|
#define CFF_FIELD_NUM( code, name, id ) \
|
||||||
CFF_FIELD( code, name, id, cff_kind_num )
|
CFF_FIELD( code, name, id, cff_kind_num )
|
||||||
#define CFF_FIELD_FIXED( code, name, id ) \
|
#define CFF_FIELD_FIXED( code, name, id ) \
|
||||||
|
@ -834,9 +863,6 @@
|
||||||
#define CFF_FIELD_BOOL( code, name, id ) \
|
#define CFF_FIELD_BOOL( code, name, id ) \
|
||||||
CFF_FIELD( code, name, id, cff_kind_bool )
|
CFF_FIELD( code, name, id, cff_kind_bool )
|
||||||
|
|
||||||
#define CFFCODE_TOPDICT 0x1000
|
|
||||||
#define CFFCODE_PRIVATE 0x2000
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FT_CONFIG_OPTION_PIC
|
#ifndef FT_CONFIG_OPTION_PIC
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,17 @@
|
||||||
FT_BEGIN_HEADER
|
FT_BEGIN_HEADER
|
||||||
|
|
||||||
|
|
||||||
|
/* CFF uses constant parser stack size; */
|
||||||
|
/* CFF2 can increase from default 193 */
|
||||||
#define CFF_MAX_STACK_DEPTH 96
|
#define CFF_MAX_STACK_DEPTH 96
|
||||||
|
#define CFF2_MAX_STACK 513
|
||||||
|
#define CFF2_DEFAULT_STACK 193
|
||||||
|
|
||||||
#define CFF_CODE_TOPDICT 0x1000
|
#define CFF_CODE_TOPDICT 0x1000
|
||||||
#define CFF_CODE_PRIVATE 0x2000
|
#define CFF_CODE_PRIVATE 0x2000
|
||||||
|
#define CFF2_CODE_TOPDICT 0x3000
|
||||||
|
#define CFF2_CODE_FONTDICT 0x4000
|
||||||
|
#define CFF2_CODE_PRIVATE 0x5000
|
||||||
|
|
||||||
|
|
||||||
typedef struct CFF_ParserRec_
|
typedef struct CFF_ParserRec_
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#define FT_STRUCTURE CFF_FontRecDictRec
|
#define FT_STRUCTURE CFF_FontRecDictRec
|
||||||
|
|
||||||
#undef CFFCODE
|
#undef CFFCODE
|
||||||
#define CFFCODE CFFCODE_TOPDICT
|
#define CFFCODE CFF_CODE_TOPDICT
|
||||||
|
|
||||||
CFF_FIELD_STRING ( 0, version, "Version" )
|
CFF_FIELD_STRING ( 0, version, "Version" )
|
||||||
CFF_FIELD_STRING ( 1, notice, "Notice" )
|
CFF_FIELD_STRING ( 1, notice, "Notice" )
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
#undef FT_STRUCTURE
|
#undef FT_STRUCTURE
|
||||||
#define FT_STRUCTURE CFF_PrivateRec
|
#define FT_STRUCTURE CFF_PrivateRec
|
||||||
#undef CFFCODE
|
#undef CFFCODE
|
||||||
#define CFFCODE CFFCODE_PRIVATE
|
#define CFFCODE CFF_CODE_PRIVATE
|
||||||
|
|
||||||
CFF_FIELD_DELTA ( 6, blue_values, 14, "BlueValues" )
|
CFF_FIELD_DELTA ( 6, blue_values, 14, "BlueValues" )
|
||||||
CFF_FIELD_DELTA ( 7, other_blues, 10, "OtherBlues" )
|
CFF_FIELD_DELTA ( 7, other_blues, 10, "OtherBlues" )
|
||||||
|
@ -102,4 +102,46 @@
|
||||||
CFF_FIELD_NUM ( 21, nominal_width, "nominalWidthX" )
|
CFF_FIELD_NUM ( 21, nominal_width, "nominalWidthX" )
|
||||||
|
|
||||||
|
|
||||||
|
#undef FT_STRUCTURE
|
||||||
|
#define FT_STRUCTURE CFF_FontRecDictRec
|
||||||
|
#undef CFFCODE
|
||||||
|
#define CFFCODE CFF2_CODE_TOPDICT
|
||||||
|
|
||||||
|
CFF_FIELD_CALLBACK( 0x107, font_matrix, "FontMatrix" )
|
||||||
|
CFF_FIELD_NUM ( 17, charstrings_offset, "CharStrings" )
|
||||||
|
CFF_FIELD_NUM ( 0x124, cid_fd_array_offset, "FDArray" )
|
||||||
|
CFF_FIELD_NUM ( 0x125, cid_fd_select_offset, "FDSelect" )
|
||||||
|
CFF_FIELD_CALLBACK( 25, maxstack, "maxstack" )
|
||||||
|
|
||||||
|
|
||||||
|
#undef FT_STRUCTURE
|
||||||
|
#define FT_STRUCTURE CFF_FontRecDictRec
|
||||||
|
#undef CFFCODE
|
||||||
|
#define CFFCODE CFF2_CODE_FONTDICT
|
||||||
|
|
||||||
|
CFF_FIELD_CALLBACK( 18, private_dict, "Private" )
|
||||||
|
CFF_FIELD_CALLBACK( 0x107, font_matrix, "FontMatrix" )
|
||||||
|
|
||||||
|
|
||||||
|
#undef FT_STRUCTURE
|
||||||
|
#define FT_STRUCTURE CFF_PrivateRec
|
||||||
|
#undef CFFCODE
|
||||||
|
#define CFFCODE CFF2_CODE_PRIVATE
|
||||||
|
|
||||||
|
CFF_FIELD_DELTA ( 6, blue_values, 14, "BlueValues" )
|
||||||
|
CFF_FIELD_DELTA ( 7, other_blues, 10, "OtherBlues" )
|
||||||
|
CFF_FIELD_DELTA ( 8, family_blues, 14, "FamilyBlues" )
|
||||||
|
CFF_FIELD_DELTA ( 9, family_other_blues, 10, "FamilyOtherBlues" )
|
||||||
|
CFF_FIELD_FIXED_1000( 0x109, blue_scale, "BlueScale" )
|
||||||
|
CFF_FIELD_NUM ( 0x10A, blue_shift, "BlueShift" )
|
||||||
|
CFF_FIELD_NUM ( 0x10B, blue_fuzz, "BlueFuzz" )
|
||||||
|
CFF_FIELD_NUM ( 10, standard_width, "StdHW" )
|
||||||
|
CFF_FIELD_NUM ( 11, standard_height, "StdVW" )
|
||||||
|
CFF_FIELD_DELTA ( 0x10C, snap_widths, 13, "StemSnapH" )
|
||||||
|
CFF_FIELD_DELTA ( 0x10D, snap_heights, 13, "StemSnapV" )
|
||||||
|
CFF_FIELD_NUM ( 0x111, language_group, "LanguageGroup" )
|
||||||
|
CFF_FIELD_FIXED ( 0x112, expansion_factor, "ExpansionFactor" )
|
||||||
|
CFF_FIELD_NUM ( 19, local_subrs_offset, "Subrs" )
|
||||||
|
|
||||||
|
|
||||||
/* END */
|
/* END */
|
||||||
|
|
|
@ -64,6 +64,7 @@ FT_BEGIN_HEADER
|
||||||
{
|
{
|
||||||
FT_Stream stream;
|
FT_Stream stream;
|
||||||
FT_ULong start;
|
FT_ULong start;
|
||||||
|
FT_UInt hdr_size;
|
||||||
FT_UInt count;
|
FT_UInt count;
|
||||||
FT_Byte off_size;
|
FT_Byte off_size;
|
||||||
FT_ULong data_offset;
|
FT_ULong data_offset;
|
||||||
|
@ -151,9 +152,16 @@ FT_BEGIN_HEADER
|
||||||
FT_UShort num_designs;
|
FT_UShort num_designs;
|
||||||
FT_UShort num_axes;
|
FT_UShort num_axes;
|
||||||
|
|
||||||
|
/* fields for CFF2 */
|
||||||
|
FT_UInt maxstack;
|
||||||
|
|
||||||
} CFF_FontRecDictRec, *CFF_FontRecDict;
|
} CFF_FontRecDictRec, *CFF_FontRecDict;
|
||||||
|
|
||||||
|
|
||||||
|
/* forward reference */
|
||||||
|
typedef struct CFF_SubFontRec_* CFF_SubFont;
|
||||||
|
|
||||||
|
|
||||||
typedef struct CFF_PrivateRec_
|
typedef struct CFF_PrivateRec_
|
||||||
{
|
{
|
||||||
FT_Byte num_blue_values;
|
FT_Byte num_blue_values;
|
||||||
|
@ -186,6 +194,9 @@ FT_BEGIN_HEADER
|
||||||
FT_Pos default_width;
|
FT_Pos default_width;
|
||||||
FT_Pos nominal_width;
|
FT_Pos nominal_width;
|
||||||
|
|
||||||
|
/* fields for CFF2 */
|
||||||
|
CFF_SubFont subfont;
|
||||||
|
|
||||||
} CFF_PrivateRec, *CFF_Private;
|
} CFF_PrivateRec, *CFF_Private;
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,10 +224,11 @@ FT_BEGIN_HEADER
|
||||||
CFF_FontRecDictRec font_dict;
|
CFF_FontRecDictRec font_dict;
|
||||||
CFF_PrivateRec private_dict;
|
CFF_PrivateRec private_dict;
|
||||||
|
|
||||||
CFF_IndexRec local_subrs_index;
|
CFF_IndexRec local_subrs_index;
|
||||||
FT_Byte** local_subrs; /* array of pointers into Local Subrs INDEX data */
|
FT_Byte** local_subrs; /* array of pointers */
|
||||||
|
/* into Local Subrs INDEX data */
|
||||||
|
|
||||||
} CFF_SubFontRec, *CFF_SubFont;
|
} CFF_SubFontRec;
|
||||||
|
|
||||||
|
|
||||||
#define CFF_MAX_CID_FONTS 256
|
#define CFF_MAX_CID_FONTS 256
|
||||||
|
@ -226,7 +238,7 @@ FT_BEGIN_HEADER
|
||||||
{
|
{
|
||||||
FT_Library library;
|
FT_Library library;
|
||||||
FT_Stream stream;
|
FT_Stream stream;
|
||||||
FT_Memory memory;
|
FT_Memory memory; /* TODO: take this from stream->memory? */
|
||||||
FT_ULong base_offset; /* offset to start of CFF */
|
FT_ULong base_offset; /* offset to start of CFF */
|
||||||
FT_UInt num_faces;
|
FT_UInt num_faces;
|
||||||
FT_UInt num_glyphs;
|
FT_UInt num_glyphs;
|
||||||
|
@ -234,8 +246,10 @@ FT_BEGIN_HEADER
|
||||||
FT_Byte version_major;
|
FT_Byte version_major;
|
||||||
FT_Byte version_minor;
|
FT_Byte version_minor;
|
||||||
FT_Byte header_size;
|
FT_Byte header_size;
|
||||||
FT_Byte absolute_offsize;
|
|
||||||
|
|
||||||
|
FT_UInt top_dict_length; /* cff2 only */
|
||||||
|
|
||||||
|
FT_Bool cff2;
|
||||||
|
|
||||||
CFF_IndexRec name_index;
|
CFF_IndexRec name_index;
|
||||||
CFF_IndexRec top_dict_index;
|
CFF_IndexRec top_dict_index;
|
||||||
|
|
|
@ -1106,12 +1106,14 @@
|
||||||
|
|
||||||
/* do we have outlines in there? */
|
/* do we have outlines in there? */
|
||||||
#ifdef FT_CONFIG_OPTION_INCREMENTAL
|
#ifdef FT_CONFIG_OPTION_INCREMENTAL
|
||||||
has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||
|
has_outline = FT_BOOL( face->root.internal->incremental_interface ||
|
||||||
tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
|
tt_face_lookup_table( face, TTAG_glyf ) != NULL ||
|
||||||
tt_face_lookup_table( face, TTAG_CFF ) != 0 );
|
tt_face_lookup_table( face, TTAG_CFF ) != NULL ||
|
||||||
|
tt_face_lookup_table( face, TTAG_CFF2 ) != NULL );
|
||||||
#else
|
#else
|
||||||
has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
|
has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != NULL ||
|
||||||
tt_face_lookup_table( face, TTAG_CFF ) != 0 );
|
tt_face_lookup_table( face, TTAG_CFF ) != NULL ||
|
||||||
|
tt_face_lookup_table( face, TTAG_CFF2 ) != NULL );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
is_apple_sbit = 0;
|
is_apple_sbit = 0;
|
||||||
|
@ -1354,6 +1356,9 @@
|
||||||
tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
|
tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
|
||||||
tt_face_lookup_table( face, TTAG_gvar ) != 0 )
|
tt_face_lookup_table( face, TTAG_gvar ) != 0 )
|
||||||
flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
|
flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
|
||||||
|
if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 &&
|
||||||
|
tt_face_lookup_table( face, TTAG_fvar ) != 0 )
|
||||||
|
flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
root->face_flags = flags;
|
root->face_flags = flags;
|
||||||
|
|
Loading…
Reference in New Issue