summaryrefslogtreecommitdiff
path: root/third_party/freetype/src/cff
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/freetype/src/cff')
-rw-r--r--third_party/freetype/src/cff/cf2arrst.c20
-rw-r--r--third_party/freetype/src/cff/cf2arrst.h6
-rw-r--r--third_party/freetype/src/cff/cf2blues.h6
-rw-r--r--third_party/freetype/src/cff/cf2error.c2
-rw-r--r--third_party/freetype/src/cff/cf2error.h10
-rw-r--r--third_party/freetype/src/cff/cf2fixed.h10
-rw-r--r--third_party/freetype/src/cff/cf2font.c54
-rw-r--r--third_party/freetype/src/cff/cf2font.h15
-rw-r--r--third_party/freetype/src/cff/cf2ft.c62
-rw-r--r--third_party/freetype/src/cff/cf2ft.h22
-rw-r--r--third_party/freetype/src/cff/cf2glue.h6
-rw-r--r--third_party/freetype/src/cff/cf2hints.c9
-rw-r--r--third_party/freetype/src/cff/cf2hints.h8
-rw-r--r--third_party/freetype/src/cff/cf2intrp.c686
-rw-r--r--third_party/freetype/src/cff/cf2intrp.h6
-rw-r--r--third_party/freetype/src/cff/cf2read.h6
-rw-r--r--third_party/freetype/src/cff/cf2stack.c159
-rw-r--r--third_party/freetype/src/cff/cf2stack.h25
-rw-r--r--third_party/freetype/src/cff/cf2types.h6
-rw-r--r--third_party/freetype/src/cff/cff.c2
-rw-r--r--third_party/freetype/src/cff/cffcmap.c39
-rw-r--r--third_party/freetype/src/cff/cffcmap.h8
-rw-r--r--third_party/freetype/src/cff/cffdrivr.c402
-rw-r--r--third_party/freetype/src/cff/cffdrivr.h8
-rw-r--r--third_party/freetype/src/cff/cfferrs.h10
-rw-r--r--third_party/freetype/src/cff/cffgload.c170
-rw-r--r--third_party/freetype/src/cff/cffgload.h11
-rw-r--r--third_party/freetype/src/cff/cffload.c981
-rw-r--r--third_party/freetype/src/cff/cffload.h58
-rw-r--r--third_party/freetype/src/cff/cffobjs.c155
-rw-r--r--third_party/freetype/src/cff/cffobjs.h8
-rw-r--r--third_party/freetype/src/cff/cffparse.c560
-rw-r--r--third_party/freetype/src/cff/cffparse.h54
-rw-r--r--third_party/freetype/src/cff/cffpic.c2
-rw-r--r--third_party/freetype/src/cff/cffpic.h9
-rw-r--r--third_party/freetype/src/cff/cfftoken.h61
-rw-r--r--third_party/freetype/src/cff/cfftypes.h138
37 files changed, 3181 insertions, 613 deletions
diff --git a/third_party/freetype/src/cff/cf2arrst.c b/third_party/freetype/src/cff/cf2arrst.c
index 89f3e9f1d7..6796450fe1 100644
--- a/third_party/freetype/src/cff/cf2arrst.c
+++ b/third_party/freetype/src/cff/cf2arrst.c
@@ -58,7 +58,7 @@
FT_Error* error,
size_t sizeItem )
{
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
/* initialize the structure */
arrstack->memory = memory;
@@ -78,7 +78,7 @@
FT_Memory memory = arrstack->memory; /* for FT_FREE */
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
arrstack->allocated = 0;
arrstack->count = 0;
@@ -95,7 +95,7 @@
cf2_arrstack_setNumElements( CF2_ArrStack arrstack,
size_t numElements )
{
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
{
FT_Error error = FT_Err_Ok; /* for FT_REALLOC */
@@ -140,7 +140,7 @@
cf2_arrstack_setCount( CF2_ArrStack arrstack,
size_t numElements )
{
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
if ( numElements > arrstack->allocated )
{
@@ -157,7 +157,7 @@
FT_LOCAL_DEF( void )
cf2_arrstack_clear( CF2_ArrStack arrstack )
{
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
arrstack->count = 0;
}
@@ -167,7 +167,7 @@
FT_LOCAL_DEF( size_t )
cf2_arrstack_size( const CF2_ArrStack arrstack )
{
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
return arrstack->count;
}
@@ -176,7 +176,7 @@
FT_LOCAL_DEF( void* )
cf2_arrstack_getBuffer( const CF2_ArrStack arrstack )
{
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
return arrstack->ptr;
}
@@ -190,7 +190,7 @@
void* newPtr;
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
if ( idx >= arrstack->count )
{
@@ -212,7 +212,7 @@
cf2_arrstack_push( CF2_ArrStack arrstack,
const void* ptr )
{
- FT_ASSERT( arrstack != NULL );
+ FT_ASSERT( arrstack );
if ( arrstack->count == arrstack->allocated )
{
@@ -225,7 +225,7 @@
}
}
- FT_ASSERT( ptr != NULL );
+ FT_ASSERT( ptr );
{
size_t offset = arrstack->count * arrstack->sizeItem;
diff --git a/third_party/freetype/src/cff/cf2arrst.h b/third_party/freetype/src/cff/cf2arrst.h
index ff5ad8b126..3c21a3b672 100644
--- a/third_party/freetype/src/cff/cf2arrst.h
+++ b/third_party/freetype/src/cff/cf2arrst.h
@@ -36,8 +36,8 @@
/***************************************************************************/
-#ifndef __CF2ARRST_H__
-#define __CF2ARRST_H__
+#ifndef CF2ARRST_H_
+#define CF2ARRST_H_
#include "cf2error.h"
@@ -94,7 +94,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2ARRST_H__ */
+#endif /* CF2ARRST_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2blues.h b/third_party/freetype/src/cff/cf2blues.h
index 2f38fcad8f..96fb60f38d 100644
--- a/third_party/freetype/src/cff/cf2blues.h
+++ b/third_party/freetype/src/cff/cf2blues.h
@@ -65,8 +65,8 @@
*/
-#ifndef __CF2BLUES_H__
-#define __CF2BLUES_H__
+#ifndef CF2BLUES_H_
+#define CF2BLUES_H_
#include "cf2glue.h"
@@ -179,7 +179,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2BLUES_H__ */
+#endif /* CF2BLUES_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2error.c b/third_party/freetype/src/cff/cf2error.c
index b5595a3d1f..e3dd69f50d 100644
--- a/third_party/freetype/src/cff/cf2error.c
+++ b/third_party/freetype/src/cff/cf2error.c
@@ -44,7 +44,7 @@
cf2_setError( FT_Error* error,
FT_Error value )
{
- if ( error && *error == 0 )
+ if ( error && !*error )
*error = value;
}
diff --git a/third_party/freetype/src/cff/cf2error.h b/third_party/freetype/src/cff/cf2error.h
index 6453ebcb7b..512edd1d21 100644
--- a/third_party/freetype/src/cff/cf2error.h
+++ b/third_party/freetype/src/cff/cf2error.h
@@ -36,13 +36,13 @@
/***************************************************************************/
-#ifndef __CF2ERROR_H__
-#define __CF2ERROR_H__
+#ifndef CF2ERROR_H_
+#define CF2ERROR_H_
#include FT_MODULE_ERRORS_H
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX CF2_Err_
@@ -70,7 +70,7 @@ FT_BEGIN_HEADER
* Upon a function call if the error code is anything other than
* `FT_Err_Ok', which is guaranteed to be zero, we
* will return without altering that error. This will allow the
- * error to propogate and be handled at the appropriate location in
+ * error to propagate and be handled at the appropriate location in
* the code.
*
* This allows a style of code where the error code is initialized
@@ -113,7 +113,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2ERROR_H__ */
+#endif /* CF2ERROR_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2fixed.h b/third_party/freetype/src/cff/cf2fixed.h
index d6d9faf8e5..2e4b5032fa 100644
--- a/third_party/freetype/src/cff/cf2fixed.h
+++ b/third_party/freetype/src/cff/cf2fixed.h
@@ -36,8 +36,8 @@
/***************************************************************************/
-#ifndef __CF2FIXED_H__
-#define __CF2FIXED_H__
+#ifndef CF2FIXED_H_
+#define CF2FIXED_H_
FT_BEGIN_HEADER
@@ -51,8 +51,8 @@ FT_BEGIN_HEADER
#define CF2_FIXED_MAX ( (CF2_Fixed)0x7FFFFFFFL )
#define CF2_FIXED_MIN ( (CF2_Fixed)0x80000000L )
-#define CF2_FIXED_ONE 0x10000L
-#define CF2_FIXED_EPSILON 0x0001
+#define CF2_FIXED_ONE ( (CF2_Fixed)0x10000L )
+#define CF2_FIXED_EPSILON ( (CF2_Fixed)0x0001 )
/* in C 89, left and right shift of negative numbers is */
/* implementation specific behaviour in the general case */
@@ -89,7 +89,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2FIXED_H__ */
+#endif /* CF2FIXED_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2font.c b/third_party/freetype/src/cff/cf2font.c
index 83fd348f2d..a86e3619b4 100644
--- a/third_party/freetype/src/cff/cf2font.c
+++ b/third_party/freetype/src/cff/cf2font.c
@@ -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 */
static void
@@ -246,6 +247,9 @@
FT_Bool needExtraSetup = FALSE;
+ CFF_VStoreRec* vstore;
+ FT_Bool hasVariations = FALSE;
+
/* character space units */
CF2_Fixed boldenX = font->syntheticEmboldeningAmountX;
CF2_Fixed boldenY = font->syntheticEmboldeningAmountY;
@@ -253,6 +257,9 @@
CFF_SubFont subFont;
CF2_Fixed ppem;
+ CF2_UInt lenNormalizedV = 0;
+ FT_Fixed* normalizedV = NULL;
+
/* clear previous error */
font->error = FT_Err_Ok;
@@ -266,6 +273,48 @@
needExtraSetup = TRUE;
}
+ /* check for variation vectors */
+ vstore = cf2_getVStore( decoder );
+ hasVariations = ( vstore->dataCount != 0 );
+
+ if ( hasVariations )
+ {
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* check whether Private DICT in this subfont needs to be reparsed */
+ font->error = cf2_getNormalizedVector( decoder,
+ &lenNormalizedV,
+ &normalizedV );
+ if ( font->error )
+ return;
+
+ if ( cff_blend_check_vector( &subFont->blend,
+ subFont->private_dict.vsindex,
+ lenNormalizedV,
+ normalizedV ) )
+ {
+ /* blend has changed, reparse */
+ cff_load_private_dict( decoder->cff,
+ subFont,
+ lenNormalizedV,
+ normalizedV );
+ needExtraSetup = TRUE;
+ }
+#endif
+
+ /* copy from subfont */
+ font->blend.font = subFont->blend.font;
+
+ /* clear state of charstring blend */
+ font->blend.usedBV = FALSE;
+
+ /* initialize value for charstring */
+ font->vsindex = subFont->private_dict.vsindex;
+
+ /* store vector inputs for blends in charstring */
+ font->lenNDV = lenNormalizedV;
+ font->NDV = normalizedV;
+ }
+
/* if ppem has changed, we need to recompute some cached data */
/* note: because of CID font matrix concatenation, ppem and transform */
/* do not necessarily track. */
@@ -423,7 +472,8 @@
/* compute blue zones for this instance */
cf2_blues_init( &font->blues, font );
- }
+
+ } /* needExtraSetup */
}
diff --git a/third_party/freetype/src/cff/cf2font.h b/third_party/freetype/src/cff/cf2font.h
index 86cf02f49d..17ecd17bbb 100644
--- a/third_party/freetype/src/cff/cf2font.h
+++ b/third_party/freetype/src/cff/cf2font.h
@@ -36,12 +36,13 @@
/***************************************************************************/
-#ifndef __CF2FONT_H__
-#define __CF2FONT_H__
+#ifndef CF2FONT_H_
+#define CF2FONT_H_
#include "cf2ft.h"
#include "cf2blues.h"
+#include "cffload.h"
FT_BEGIN_HEADER
@@ -54,6 +55,7 @@ FT_BEGIN_HEADER
/* (Hiragino Kaku Gothic ProN W3; */
/* 8.2d6e1; 2014-12-19) that exceed */
/* this limit */
+#define CF2_STORAGE_SIZE 32
/* typedef is in `cf2glue.h' */
@@ -62,6 +64,7 @@ FT_BEGIN_HEADER
FT_Memory memory;
FT_Error error; /* shared error for this instance */
+ FT_Bool isCFF2;
CF2_RenderingFlags renderingFlags;
/* variables that depend on Transform: */
@@ -73,6 +76,12 @@ FT_BEGIN_HEADER
CF2_Matrix outerTransform; /* post hinting; includes rotations */
CF2_Fixed ppem; /* transform-dependent */
+ /* variation data */
+ CFF_BlendRec blend; /* cached charstring blend vector */
+ CF2_UInt vsindex; /* current vsindex */
+ CF2_UInt lenNDV; /* current length NDV or zero */
+ FT_Fixed* NDV; /* ptr to current NDV or NULL */
+
CF2_Int unitsPerEm;
CF2_Fixed syntheticEmboldeningAmountX; /* character space units */
@@ -115,7 +124,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2FONT_H__ */
+#endif /* CF2FONT_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2ft.c b/third_party/freetype/src/cff/cf2ft.c
index d2544a2345..c0d067e94e 100644
--- a/third_party/freetype/src/cff/cf2ft.c
+++ b/third_party/freetype/src/cff/cf2ft.c
@@ -104,7 +104,8 @@
FT_Memory memory = font->memory;
- (void)memory;
+ FT_FREE( font->blend.lastNDV );
+ FT_FREE( font->blend.BV );
}
}
@@ -239,7 +240,7 @@
FT_Memory memory,
FT_Error* error )
{
- FT_MEM_ZERO( outline, sizeof ( CF2_OutlineRec ) );
+ FT_ZERO( outline );
outline->root.memory = memory;
outline->root.error = error;
@@ -311,7 +312,7 @@
font = (CF2_Font)decoder->cff->cf2_instance.data;
/* on first glyph, allocate instance structure */
- if ( decoder->cff->cf2_instance.data == NULL )
+ if ( !decoder->cff->cf2_instance.data )
{
decoder->cff->cf2_instance.finalizer =
(FT_Generic_Finalizer)cf2_free_instance;
@@ -366,6 +367,9 @@
&hinted,
&scaled );
+ /* copy isCFF2 boolean from TT_Face to CF2_Font */
+ font->isCFF2 = builder->face->isCFF2;
+
font->renderingFlags = 0;
if ( hinted )
font->renderingFlags |= CF2_FlagsHinted;
@@ -413,6 +417,44 @@
}
+ /* get pointer to VStore structure */
+ FT_LOCAL_DEF( CFF_VStore )
+ cf2_getVStore( CFF_Decoder* decoder )
+ {
+ FT_ASSERT( decoder && decoder->cff );
+
+ return &decoder->cff->vstore;
+ }
+
+
+ /* 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;
+ }
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* Get normalized design vector for current render request; */
+ /* return pointer and length. */
+ /* */
+ /* Note: Uses FT_Fixed not CF2_Fixed for the vector. */
+ FT_LOCAL_DEF( FT_Error )
+ cf2_getNormalizedVector( CFF_Decoder* decoder,
+ CF2_UInt *len,
+ FT_Fixed* *vec )
+ {
+ FT_ASSERT( decoder && decoder->builder.face );
+ FT_ASSERT( vec && len );
+
+ return cff_get_var_blend( decoder->builder.face, len, vec, NULL );
+ }
+#endif
+
+
/* get `y_ppem' from `CFF_Size' */
FT_LOCAL_DEF( CF2_Fixed )
cf2_getPpemY( CFF_Decoder* decoder )
@@ -544,14 +586,17 @@
/* return 0 on success */
FT_LOCAL_DEF( CF2_Int )
cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf )
{
+ CF2_UInt idx;
+
+
FT_ASSERT( decoder );
FT_ZERO( buf );
- idx += (CF2_UInt)decoder->globals_bias;
+ idx = (CF2_UInt)( subrNum + decoder->globals_bias );
if ( idx >= decoder->num_globals )
return TRUE; /* error */
@@ -628,14 +673,17 @@
FT_LOCAL_DEF( CF2_Int )
cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf )
{
+ CF2_UInt idx;
+
+
FT_ASSERT( decoder );
FT_ZERO( buf );
- idx += (CF2_UInt)decoder->locals_bias;
+ idx = (CF2_UInt)( subrNum + decoder->locals_bias );
if ( idx >= decoder->num_locals )
return TRUE; /* error */
diff --git a/third_party/freetype/src/cff/cf2ft.h b/third_party/freetype/src/cff/cf2ft.h
index 3073df382f..b054a6e950 100644
--- a/third_party/freetype/src/cff/cf2ft.h
+++ b/third_party/freetype/src/cff/cf2ft.h
@@ -36,8 +36,8 @@
/***************************************************************************/
-#ifndef __CF2FT_H__
-#define __CF2FT_H__
+#ifndef CF2FT_H_
+#define CF2FT_H_
#include "cf2types.h"
@@ -64,6 +64,18 @@ FT_BEGIN_HEADER
FT_LOCAL( CFF_SubFont )
cf2_getSubfont( CFF_Decoder* decoder );
+ FT_LOCAL( CFF_VStore )
+ cf2_getVStore( CFF_Decoder* decoder );
+
+ FT_LOCAL( FT_UInt )
+ cf2_getMaxstack( CFF_Decoder* decoder );
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ FT_LOCAL( FT_Error )
+ cf2_getNormalizedVector( CFF_Decoder* decoder,
+ CF2_UInt *len,
+ FT_Fixed* *vec );
+#endif
FT_LOCAL( CF2_Fixed )
cf2_getPpemY( CFF_Decoder* decoder );
@@ -99,7 +111,7 @@ FT_BEGIN_HEADER
FT_LOCAL( CF2_Int )
cf2_initGlobalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf );
FT_LOCAL( FT_Error )
cf2_getSeacComponent( CFF_Decoder* decoder,
@@ -110,7 +122,7 @@ FT_BEGIN_HEADER
CF2_Buffer buf );
FT_LOCAL( CF2_Int )
cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
- CF2_UInt idx,
+ CF2_Int subrNum,
CF2_Buffer buf );
FT_LOCAL( CF2_Fixed )
@@ -141,7 +153,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2FT_H__ */
+#endif /* CF2FT_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2glue.h b/third_party/freetype/src/cff/cf2glue.h
index a24da39e93..56a7c248f4 100644
--- a/third_party/freetype/src/cff/cf2glue.h
+++ b/third_party/freetype/src/cff/cf2glue.h
@@ -36,8 +36,8 @@
/***************************************************************************/
-#ifndef __CF2GLUE_H__
-#define __CF2GLUE_H__
+#ifndef CF2GLUE_H_
+#define CF2GLUE_H_
/* common includes for other modules */
@@ -138,7 +138,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2GLUE_H__ */
+#endif /* CF2GLUE_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2hints.c b/third_party/freetype/src/cff/cf2hints.c
index 0e27000210..c8f7dfeba6 100644
--- a/third_party/freetype/src/cff/cf2hints.c
+++ b/third_party/freetype/src/cff/cf2hints.c
@@ -401,10 +401,10 @@
/* calculate all four possibilities; moves down are negative */
CF2_Fixed downMoveDown = 0 - fracDown;
CF2_Fixed upMoveDown = 0 - fracUp;
- CF2_Fixed downMoveUp = fracDown == 0
+ CF2_Fixed downMoveUp = ( fracDown == 0 )
? 0
: cf2_intToFixed( 1 ) - fracDown;
- CF2_Fixed upMoveUp = fracUp == 0
+ CF2_Fixed upMoveUp = ( fracUp == 0 )
? 0
: cf2_intToFixed( 1 ) - fracUp;
@@ -587,8 +587,9 @@
}
/* paired edges must be in proper order */
- FT_ASSERT( !isPair ||
- topHintEdge->csCoord >= bottomHintEdge->csCoord );
+ if ( isPair &&
+ topHintEdge->csCoord < bottomHintEdge->csCoord )
+ return;
/* linear search to find index value of insertion point */
indexInsert = 0;
diff --git a/third_party/freetype/src/cff/cf2hints.h b/third_party/freetype/src/cff/cf2hints.h
index f25d91bf89..a8984542a0 100644
--- a/third_party/freetype/src/cff/cf2hints.h
+++ b/third_party/freetype/src/cff/cf2hints.h
@@ -36,8 +36,8 @@
/***************************************************************************/
-#ifndef __CF2HINTS_H__
-#define __CF2HINTS_H__
+#ifndef CF2HINTS_H_
+#define CF2HINTS_H_
FT_BEGIN_HEADER
@@ -220,7 +220,7 @@ FT_BEGIN_HEADER
/* character space miter limit threshold */
CF2_Fixed miterLimit;
- /* vertical/horzizontal snap distance in character space */
+ /* vertical/horizontal snap distance in character space */
CF2_Fixed snapThreshold;
FT_Vector offsetStart0; /* first and second points of first */
@@ -283,7 +283,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2HINTS_H__ */
+#endif /* CF2HINTS_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2intrp.c b/third_party/freetype/src/cff/cf2intrp.c
index ff3fa9aaaa..6bf298a4d6 100644
--- a/third_party/freetype/src/cff/cf2intrp.c
+++ b/third_party/freetype/src/cff/cf2intrp.c
@@ -47,6 +47,8 @@
#include "cf2error.h"
+#include "cffload.h"
+
/*************************************************************************/
/* */
@@ -184,7 +186,7 @@
return;
FT_ASSERT( hintmask->byteCount > 0 );
- FT_ASSERT( hintmask->byteCount <
+ FT_ASSERT( hintmask->byteCount <=
sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
/* set mask to all ones */
@@ -215,8 +217,8 @@
cf2_cmdESC, /* 12 */
cf2_cmdRESERVED_13, /* 13 */
cf2_cmdENDCHAR, /* 14 */
- cf2_cmdRESERVED_15, /* 15 */
- cf2_cmdRESERVED_16, /* 16 */
+ cf2_cmdVSINDEX, /* 15 */
+ cf2_cmdBLEND, /* 16 */
cf2_cmdRESERVED_17, /* 17 */
cf2_cmdHSTEMHM, /* 18 */
cf2_cmdHINTMASK, /* 19 */
@@ -273,7 +275,8 @@
cf2_escHFLEX, /* 34 */
cf2_escFLEX, /* 35 */
cf2_escHFLEX1, /* 36 */
- cf2_escFLEX1 /* 37 */
+ cf2_escFLEX1, /* 37 */
+ cf2_escRESERVED_38 /* 38 & all higher */
};
@@ -293,7 +296,8 @@
/* variable accumulates delta values from operand stack */
CF2_Fixed position = hintOffset;
- if ( hasWidthArg && ! *haveWidth )
+
+ if ( hasWidthArg && !*haveWidth )
*width = cf2_stack_getReal( opStack, 0 ) +
cf2_getNominalWidthX( font->decoder );
@@ -343,7 +347,7 @@
vals[0] = *curX;
vals[1] = *curY;
index = 0;
- isHFlex = readFromStack[9] == FALSE;
+ isHFlex = FT_BOOL( readFromStack[9] == FALSE );
top = isHFlex ? 9 : 10;
for ( i = 0; i < top; i++ )
@@ -402,6 +406,43 @@
}
+ /* Blend numOperands on the stack, */
+ /* store results into the first numBlends values, */
+ /* then pop remaining arguments. */
+ static void
+ cf2_doBlend( const CFF_Blend blend,
+ CF2_Stack opStack,
+ CF2_UInt numBlends )
+ {
+ CF2_UInt delta;
+ CF2_UInt base;
+ CF2_UInt i, j;
+ CF2_UInt numOperands = (CF2_UInt)( numBlends * blend->lenBV );
+
+
+ base = cf2_stack_count( opStack ) - numOperands;
+ delta = base + numBlends;
+
+ for ( i = 0; i < numBlends; i++ )
+ {
+ const CF2_Fixed* weight = &blend->BV[1];
+
+ /* start with first term */
+ CF2_Fixed sum = cf2_stack_getReal( opStack, i + base );
+
+
+ for ( j = 1; j < blend->lenBV; j++ )
+ sum += FT_MulFix( *weight++, cf2_stack_getReal( opStack, delta++ ) );
+
+ /* store blended result */
+ cf2_stack_setReal( opStack, i + base, sum );
+ }
+
+ /* leave only `numBlends' results on stack */
+ cf2_stack_pop( opStack, numOperands - numBlends );
+ }
+
+
/*
* `error' is a shared error code used by many objects in this
* routine. Before the code continues from an error, it must check and
@@ -444,8 +485,11 @@
CF2_Fixed hintOriginY = curY;
CF2_Stack opStack = NULL;
+ FT_UInt stackSize;
FT_Byte op1; /* first opcode byte */
+ CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */
+
/* instruction limit; 20,000,000 matches Avalon */
FT_UInt32 instructionLimit = 20000000UL;
@@ -466,6 +510,8 @@
CF2_GlyphPathRec glyphPath;
+ FT_ZERO( &storage );
+
/* initialize the remaining objects */
cf2_arrstack_init( &subrStack,
memory,
@@ -515,19 +561,24 @@
* If one of the above operators occurs without explicitly specifying
* 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 );
/*
- * Note: at this point, all pointers to resources must be NULL
- * and all local objects must be initialized.
- * There must be no branches to exit: above this point.
+ * Note: At this point, all pointers to resources must be NULL
+ * and all local objects must be initialized.
+ * There must be no branches to `exit:' above this point.
*
*/
/* allocate an operand stack */
- opStack = cf2_stack_init( memory, error );
+ stackSize = font->isCFF2 ? cf2_getMaxstack( decoder )
+ : CF2_OPERAND_STACK_SIZE;
+ opStack = cf2_stack_init( memory, error, stackSize );
+
if ( !opStack )
{
lastError = FT_THROW( Out_Of_Memory );
@@ -556,14 +607,23 @@
{
/* If we've reached the end of the charstring, simulate a */
/* cf2_cmdRETURN or cf2_cmdENDCHAR. */
+ /* We do this for both CFF and CFF2. */
if ( charstringIndex )
op1 = cf2_cmdRETURN; /* end of buffer for subroutine */
else
op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
}
else
+ {
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 */
if ( *error )
goto exit;
@@ -581,13 +641,78 @@
case cf2_cmdRESERVED_2:
case cf2_cmdRESERVED_9:
case cf2_cmdRESERVED_13:
- case cf2_cmdRESERVED_15:
- case cf2_cmdRESERVED_16:
case cf2_cmdRESERVED_17:
/* we may get here if we have a prior error */
FT_TRACE4(( " unknown op (%d)\n", op1 ));
break;
+ case cf2_cmdVSINDEX:
+ FT_TRACE4(( " vsindex\n" ));
+
+ if ( !font->isCFF2 )
+ break; /* clear stack & ignore */
+
+ if ( font->blend.usedBV )
+ {
+ /* vsindex not allowed after blend */
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ {
+ FT_Int temp = cf2_stack_popInt( opStack );
+
+
+ if ( temp >= 0 )
+ font->vsindex = (FT_UInt)temp;
+ }
+ break;
+
+ case cf2_cmdBLEND:
+ {
+ FT_UInt numBlends;
+
+
+ FT_TRACE4(( " blend\n" ));
+
+ if ( !font->isCFF2 )
+ break; /* clear stack & ignore */
+
+ /* do we have a `blend' op in a non-variant font? */
+ if ( !font->blend.font )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ /* check cached blend vector */
+ if ( cff_blend_check_vector( &font->blend,
+ font->vsindex,
+ font->lenNDV,
+ font->NDV ) )
+ {
+ lastError = cff_blend_build_vector( &font->blend,
+ font->vsindex,
+ font->lenNDV,
+ font->NDV );
+ if ( lastError )
+ goto exit;
+ }
+
+ /* do the blend */
+ numBlends = (FT_UInt)cf2_stack_popInt( opStack );
+ if ( numBlends > stackSize )
+ {
+ lastError = FT_THROW( Invalid_Glyph_Format );
+ goto exit;
+ }
+
+ cf2_doBlend( &font->blend, opStack, numBlends );
+
+ font->blend.usedBV = TRUE;
+ }
+ continue; /* do not clear the stack */
+
case cf2_cmdHSTEMHM:
case cf2_cmdHSTEM:
FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
@@ -608,7 +733,7 @@
0 );
if ( font->decoder->width_only )
- goto exit;
+ goto exit;
break;
@@ -632,7 +757,7 @@
0 );
if ( font->decoder->width_only )
- goto exit;
+ goto exit;
break;
@@ -646,7 +771,7 @@
haveWidth = TRUE;
if ( font->decoder->width_only )
- goto exit;
+ goto exit;
curY += cf2_stack_popFixed( opStack );
@@ -680,7 +805,7 @@
CF2_UInt index;
CF2_UInt count = cf2_stack_count( opStack );
- FT_Bool isX = op1 == cf2_cmdHLINETO;
+ FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO );
FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
@@ -746,7 +871,7 @@
case cf2_cmdCALLGSUBR:
case cf2_cmdCALLSUBR:
{
- CF2_UInt subrIndex;
+ CF2_Int subrNum;
FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
@@ -766,17 +891,17 @@
(size_t)charstringIndex + 1 );
/* set up the new CFF region and pointer */
- subrIndex = (CF2_UInt)cf2_stack_popInt( opStack );
+ subrNum = cf2_stack_popInt( opStack );
switch ( op1 )
{
case cf2_cmdCALLGSUBR:
FT_TRACE4(( " (idx %d, entering level %d)\n",
- subrIndex + (CF2_UInt)decoder->globals_bias,
+ subrNum + decoder->globals_bias,
charstringIndex + 1 ));
if ( cf2_initGlobalRegionBuffer( decoder,
- subrIndex,
+ subrNum,
charstring ) )
{
lastError = FT_THROW( Invalid_Glyph_Format );
@@ -787,11 +912,11 @@
default:
/* cf2_cmdCALLSUBR */
FT_TRACE4(( " (idx %d, entering level %d)\n",
- subrIndex + (CF2_UInt)decoder->locals_bias,
+ subrNum + decoder->locals_bias,
charstringIndex + 1 ));
if ( cf2_initLocalRegionBuffer( decoder,
- subrIndex,
+ subrNum,
charstring ) )
{
lastError = FT_THROW( Invalid_Glyph_Format );
@@ -825,135 +950,10 @@
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 )
{
- case cf2_escDOTSECTION:
- /* something about `flip type of locking' -- ignore it */
- FT_TRACE4(( " dotsection\n" ));
-
- break;
-
- /* TODO: should these operators be supported? */
- case cf2_escAND: /* in spec */
- FT_TRACE4(( " and\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escOR: /* in spec */
- FT_TRACE4(( " or\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escNOT: /* in spec */
- FT_TRACE4(( " not\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escABS: /* in spec */
- FT_TRACE4(( " abs\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escADD: /* in spec */
- FT_TRACE4(( " add\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escSUB: /* in spec */
- FT_TRACE4(( " sub\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escDIV: /* in spec */
- FT_TRACE4(( " div\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escNEG: /* in spec */
- FT_TRACE4(( " neg\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escEQ: /* in spec */
- FT_TRACE4(( " eq\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escDROP: /* in spec */
- FT_TRACE4(( " drop\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escPUT: /* in spec */
- FT_TRACE4(( " put\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escGET: /* in spec */
- FT_TRACE4(( " get\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escIFELSE: /* in spec */
- FT_TRACE4(( " ifelse\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escRANDOM: /* in spec */
- FT_TRACE4(( " random\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escMUL: /* in spec */
- FT_TRACE4(( " mul\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escSQRT: /* in spec */
- FT_TRACE4(( " sqrt\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escDUP: /* in spec */
- FT_TRACE4(( " dup\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escEXCH: /* in spec */
- FT_TRACE4(( " exch\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escINDEX: /* in spec */
- FT_TRACE4(( " index\n" ));
-
- CF2_FIXME;
- break;
-
- case cf2_escROLL: /* in spec */
- FT_TRACE4(( " roll\n" ));
-
- CF2_FIXME;
- break;
-
case cf2_escHFLEX:
{
static const FT_Bool readFromStack[12] =
@@ -1050,6 +1050,7 @@
}
continue;
+ /* these opcodes are reserved in both CFF & CFF2 */
case cf2_escRESERVED_1:
case cf2_escRESERVED_2:
case cf2_escRESERVED_6:
@@ -1063,12 +1064,342 @@
case cf2_escRESERVED_31:
case cf2_escRESERVED_32:
case cf2_escRESERVED_33:
- default:
FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+ break;
+
+ default:
+ {
+ 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 )
+ {
+
+ 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" ));
- }; /* end of switch statement checking `op2' */
+ 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 */
+
break;
case cf2_cmdENDCHAR:
@@ -1085,12 +1416,13 @@
haveWidth = TRUE;
if ( font->decoder->width_only )
- goto exit;
+ goto exit;
/* close path if still open */
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 -- */
/* this is a (deprecated) implied `seac' operator */
@@ -1117,8 +1449,8 @@
error2 = cf2_getSeacComponent( decoder, achar, &component );
if ( error2 )
{
- lastError = error2; /* pass FreeType error through */
- goto exit;
+ lastError = error2; /* pass FreeType error through */
+ goto exit;
}
cf2_interpT2CharString( font,
&component,
@@ -1172,7 +1504,7 @@
0 );
if ( font->decoder->width_only )
- goto exit;
+ goto exit;
if ( op1 == cf2_cmdHINTMASK )
{
@@ -1231,7 +1563,7 @@
haveWidth = TRUE;
if ( font->decoder->width_only )
- goto exit;
+ goto exit;
curY += cf2_stack_popFixed( opStack );
curX += cf2_stack_popFixed( opStack );
@@ -1250,7 +1582,7 @@
haveWidth = TRUE;
if ( font->decoder->width_only )
- goto exit;
+ goto exit;
curX += cf2_stack_popFixed( opStack );
@@ -1319,7 +1651,7 @@
{
x1 = cf2_stack_getReal( opStack, index ) + curX;
- ++index;
+ index++;
}
else
x1 = curX;
@@ -1364,7 +1696,7 @@
{
y1 = cf2_stack_getReal( opStack, index ) + curY;
- ++index;
+ index++;
}
else
y1 = curY;
@@ -1392,7 +1724,7 @@
CF2_UInt count, count1 = cf2_stack_count( opStack );
CF2_UInt index = 0;
- FT_Bool alternate = op1 == cf2_cmdHVCURVETO;
+ FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO );
/* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
@@ -1421,7 +1753,7 @@
{
x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
- ++index;
+ index++;
}
else
x3 = x2;
@@ -1440,7 +1772,7 @@
{
y3 = cf2_stack_getReal( opStack, index + 4 ) + y2;
- ++index;
+ index++;
}
else
y3 = y2;
@@ -1463,9 +1795,12 @@
{
CF2_Int v;
+ CF2_Int byte1 = cf2_buf_readByte( charstring );
+ CF2_Int byte2 = cf2_buf_readByte( charstring );
+
- v = (FT_Short)( ( cf2_buf_readByte( charstring ) << 8 ) |
- cf2_buf_readByte( charstring ) );
+ v = (FT_Short)( ( byte1 << 8 ) |
+ byte2 );
FT_TRACE4(( " %d", v ));
@@ -1527,14 +1862,18 @@
{
CF2_Fixed v;
+ FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring );
+ FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring );
+ FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring );
+ FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring );
- v = (CF2_Fixed)
- ( ( (FT_UInt32)cf2_buf_readByte( charstring ) << 24 ) |
- ( (FT_UInt32)cf2_buf_readByte( charstring ) << 16 ) |
- ( (FT_UInt32)cf2_buf_readByte( charstring ) << 8 ) |
- (FT_UInt32)cf2_buf_readByte( charstring ) );
- FT_TRACE4(( " %.2f", v / 65536.0 ));
+ v = (CF2_Fixed)( ( byte1 << 24 ) |
+ ( byte2 << 16 ) |
+ ( byte3 << 8 ) |
+ byte4 );
+
+ FT_TRACE4(( " %.5f", v / 65536.0 ));
cf2_stack_pushFixed( opStack, v );
}
@@ -1555,6 +1894,9 @@
/* check whether last error seen is also the first one */
cf2_setError( error, lastError );
+ if ( *error )
+ FT_TRACE4(( "charstring error %d\n", *error ));
+
/* free resources from objects we've used */
cf2_glyphpath_finalize( &glyphPath );
cf2_arrstack_finalize( &vStemHintArray );
diff --git a/third_party/freetype/src/cff/cf2intrp.h b/third_party/freetype/src/cff/cf2intrp.h
index b5d8947838..ec030e8944 100644
--- a/third_party/freetype/src/cff/cf2intrp.h
+++ b/third_party/freetype/src/cff/cf2intrp.h
@@ -36,8 +36,8 @@
/***************************************************************************/
-#ifndef __CF2INTRP_H__
-#define __CF2INTRP_H__
+#ifndef CF2INTRP_H_
+#define CF2INTRP_H_
#include "cf2ft.h"
@@ -77,7 +77,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2INTRP_H__ */
+#endif /* CF2INTRP_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2read.h b/third_party/freetype/src/cff/cf2read.h
index 7ef7c8c149..b0b0db803a 100644
--- a/third_party/freetype/src/cff/cf2read.h
+++ b/third_party/freetype/src/cff/cf2read.h
@@ -36,8 +36,8 @@
/***************************************************************************/
-#ifndef __CF2READ_H__
-#define __CF2READ_H__
+#ifndef CF2READ_H_
+#define CF2READ_H_
FT_BEGIN_HEADER
@@ -62,7 +62,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2READ_H__ */
+#endif /* CF2READ_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2stack.c b/third_party/freetype/src/cff/cf2stack.c
index 8332b5d91a..12a026d21d 100644
--- a/third_party/freetype/src/cff/cf2stack.c
+++ b/third_party/freetype/src/cff/cf2stack.c
@@ -51,21 +51,31 @@
/* `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 */
+ FT_Error error = FT_Err_Ok; /* for FT_NEW */
CF2_Stack stack = NULL;
- if ( !FT_QNEW( stack ) )
+ if ( !FT_NEW( stack ) )
{
- /* initialize the structure; FT_QNEW zeroes it */
+ /* initialize the structure; FT_NEW 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 */
@@ -103,7 +115,7 @@
stack->top->u.i = val;
stack->top->type = CF2_NumberInt;
- ++stack->top;
+ stack->top++;
}
@@ -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 */
@@ -119,7 +131,7 @@
stack->top->u.r = val;
stack->top->type = CF2_NumberFixed;
- ++stack->top;
+ stack->top++;
}
@@ -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 */
@@ -138,24 +150,24 @@
return 0; /* type mismatch */
}
- --stack->top;
+ stack->top--;
return stack->top->u.i;
}
/* Note: type mismatch is silently cast */
- /* TODO: check this */
+ /* TODO: check this */
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 */
}
- --stack->top;
+ stack->top--;
switch ( stack->top->type )
{
@@ -170,12 +182,12 @@
/* Note: type mismatch is silently cast */
- /* TODO: check this */
+ /* TODO: check this */
FT_LOCAL_DEF( CF2_Fixed )
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 ) )
{
@@ -195,10 +207,121 @@
}
+ /* provide random access to stack */
+ FT_LOCAL_DEF( void )
+ cf2_stack_setReal( CF2_Stack stack,
+ CF2_UInt idx,
+ CF2_Fixed val )
+ {
+ if ( idx > cf2_stack_count( stack ) )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Overflow );
+ return;
+ }
+
+ stack->buffer[idx].u.r = val;
+ stack->buffer[idx].type = CF2_NumberFixed;
+ }
+
+
+ /* discard (pop) num values from stack */
+ FT_LOCAL_DEF( void )
+ cf2_stack_pop( CF2_Stack stack,
+ CF2_UInt num )
+ {
+ if ( num > cf2_stack_count( stack ) )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Underflow );
+ return;
+ }
+ stack->top -= num;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cf2_stack_roll( CF2_Stack stack,
+ CF2_Int count,
+ CF2_Int shift )
+ {
+ /* we initialize this variable to avoid compiler warnings */
+ CF2_StackNumber last = { { 0 }, CF2_NumberInt };
+
+ CF2_Int start_idx, idx, i;
+
+
+ if ( count < 2 )
+ return; /* nothing to do (values 0 and 1), or undefined value */
+
+ if ( (CF2_UInt)count > cf2_stack_count( stack ) )
+ {
+ CF2_SET_ERROR( stack->error, Stack_Overflow );
+ return;
+ }
+
+ if ( shift < 0 )
+ shift = -( ( -shift ) % count );
+ else
+ shift %= count;
+
+ if ( shift == 0 )
+ return; /* nothing to do */
+
+ /* We use the following algorithm to do the rolling, */
+ /* which needs two temporary variables only. */
+ /* */
+ /* Example: */
+ /* */
+ /* count = 8 */
+ /* shift = 2 */
+ /* */
+ /* stack indices before roll: 7 6 5 4 3 2 1 0 */
+ /* stack indices after roll: 1 0 7 6 5 4 3 2 */
+ /* */
+ /* The value of index 0 gets moved to index 2, while */
+ /* the old value of index 2 gets moved to index 4, */
+ /* and so on. We thus have the following copying */
+ /* chains for shift value 2. */
+ /* */
+ /* 0 -> 2 -> 4 -> 6 -> 0 */
+ /* 1 -> 3 -> 5 -> 7 -> 1 */
+ /* */
+ /* If `count' and `shift' are incommensurable, we */
+ /* have a single chain only. Otherwise, increase */
+ /* the start index by 1 after the first chain, then */
+ /* do the next chain until all elements in all */
+ /* chains are handled. */
+
+ start_idx = -1;
+ idx = -1;
+ for ( i = 0; i < count; i++ )
+ {
+ CF2_StackNumber tmp;
+
+
+ if ( start_idx == idx )
+ {
+ start_idx++;
+ idx = start_idx;
+ last = stack->buffer[idx];
+ }
+
+ idx += shift;
+ if ( idx >= count )
+ idx -= count;
+ else if ( idx < 0 )
+ idx += count;
+
+ tmp = stack->buffer[idx];
+ stack->buffer[idx] = last;
+ last = tmp;
+ }
+ }
+
+
FT_LOCAL_DEF( void )
cf2_stack_clear( CF2_Stack stack )
{
- stack->top = &stack->buffer[0];
+ stack->top = stack->buffer;
}
diff --git a/third_party/freetype/src/cff/cf2stack.h b/third_party/freetype/src/cff/cf2stack.h
index 7d6d1961fe..ef08eefe41 100644
--- a/third_party/freetype/src/cff/cf2stack.h
+++ b/third_party/freetype/src/cff/cf2stack.h
@@ -36,8 +36,8 @@
/***************************************************************************/
-#ifndef __CF2STACK_H__
-#define __CF2STACK_H__
+#ifndef CF2STACK_H_
+#define CF2STACK_H_
FT_BEGIN_HEADER
@@ -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 );
@@ -92,6 +94,19 @@ FT_BEGIN_HEADER
FT_LOCAL( CF2_Fixed )
cf2_stack_getReal( CF2_Stack stack,
CF2_UInt idx );
+ FT_LOCAL( void )
+ cf2_stack_setReal( CF2_Stack stack,
+ CF2_UInt idx,
+ CF2_Fixed val );
+
+ FT_LOCAL( void )
+ cf2_stack_pop( CF2_Stack stack,
+ CF2_UInt num );
+
+ FT_LOCAL( void )
+ cf2_stack_roll( CF2_Stack stack,
+ CF2_Int count,
+ CF2_Int idx );
FT_LOCAL( void )
cf2_stack_clear( CF2_Stack stack );
@@ -100,7 +115,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2STACK_H__ */
+#endif /* CF2STACK_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cf2types.h b/third_party/freetype/src/cff/cf2types.h
index ac6a02266e..5b7e1239af 100644
--- a/third_party/freetype/src/cff/cf2types.h
+++ b/third_party/freetype/src/cff/cf2types.h
@@ -36,8 +36,8 @@
/***************************************************************************/
-#ifndef __CF2TYPES_H__
-#define __CF2TYPES_H__
+#ifndef CF2TYPES_H_
+#define CF2TYPES_H_
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -72,7 +72,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CF2TYPES_H__ */
+#endif /* CF2TYPES_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cff.c b/third_party/freetype/src/cff/cff.c
index bb2cfb5253..545fb202c9 100644
--- a/third_party/freetype/src/cff/cff.c
+++ b/third_party/freetype/src/cff/cff.c
@@ -4,7 +4,7 @@
/* */
/* FreeType OpenType driver component (body only). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/third_party/freetype/src/cff/cffcmap.c b/third_party/freetype/src/cff/cffcmap.c
index e7538e9840..4adce7a54d 100644
--- a/third_party/freetype/src/cff/cffcmap.c
+++ b/third_party/freetype/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
/* */
/* CFF character mapping table (cmap) support (body). */
/* */
-/* Copyright 2002-2015 by */
+/* Copyright 2002-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -104,15 +104,21 @@
}
- FT_DEFINE_CMAP_CLASS(cff_cmap_encoding_class_rec,
+ FT_DEFINE_CMAP_CLASS(
+ cff_cmap_encoding_class_rec,
+
sizeof ( CFF_CMapStdRec ),
- (FT_CMap_InitFunc) cff_cmap_encoding_init,
- (FT_CMap_DoneFunc) cff_cmap_encoding_done,
- (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index,
- (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next,
+ (FT_CMap_InitFunc) cff_cmap_encoding_init, /* init */
+ (FT_CMap_DoneFunc) cff_cmap_encoding_done, /* done */
+ (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index, /* char_index */
+ (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next, /* char_next */
- NULL, NULL, NULL, NULL, NULL
+ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */
+ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */
+ (FT_CMap_VariantListFunc) NULL, /* variant_list */
+ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */
+ (FT_CMap_VariantCharListFunc) NULL /* variantchar_list */
)
@@ -202,15 +208,22 @@
}
- FT_DEFINE_CMAP_CLASS(cff_cmap_unicode_class_rec,
+ FT_DEFINE_CMAP_CLASS(
+ cff_cmap_unicode_class_rec,
+
sizeof ( PS_UnicodesRec ),
- (FT_CMap_InitFunc) cff_cmap_unicode_init,
- (FT_CMap_DoneFunc) cff_cmap_unicode_done,
- (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index,
- (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next,
+ (FT_CMap_InitFunc) cff_cmap_unicode_init, /* init */
+ (FT_CMap_DoneFunc) cff_cmap_unicode_done, /* done */
+ (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index, /* char_index */
+ (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next, /* char_next */
- NULL, NULL, NULL, NULL, NULL
+ (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */
+ (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */
+ (FT_CMap_VariantListFunc) NULL, /* variant_list */
+ (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */
+ (FT_CMap_VariantCharListFunc) NULL /* variantchar_list */
)
+
/* END */
diff --git a/third_party/freetype/src/cff/cffcmap.h b/third_party/freetype/src/cff/cffcmap.h
index 6eaed636ec..7792e04248 100644
--- a/third_party/freetype/src/cff/cffcmap.h
+++ b/third_party/freetype/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
/* */
/* CFF character mapping table (cmap) support (specification). */
/* */
-/* Copyright 2002-2015 by */
+/* Copyright 2002-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,8 +16,8 @@
/***************************************************************************/
-#ifndef __CFFCMAP_H__
-#define __CFFCMAP_H__
+#ifndef CFFCMAP_H_
+#define CFFCMAP_H_
#include "cffobjs.h"
@@ -61,7 +61,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CFFCMAP_H__ */
+#endif /* CFFCMAP_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cffdrivr.c b/third_party/freetype/src/cff/cffdrivr.c
index a718b7a002..467b3edc70 100644
--- a/third_party/freetype/src/cff/cffdrivr.c
+++ b/third_party/freetype/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
/* */
/* OpenType font driver implementation (body). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -32,6 +32,10 @@
#include "cffcmap.h"
#include "cffparse.h"
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+#endif
+
#include "cfferrs.h"
#include "cffpic.h"
@@ -207,6 +211,13 @@
if ( flags & FT_LOAD_VERTICAL_LAYOUT )
{
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* no fast retrieval for blended MM fonts without VVAR table */
+ if ( !ttface->is_default_instance &&
+ !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+ return FT_THROW( Unimplemented_Feature );
+#endif
+
/* check whether we have data from the `vmtx' table at all; */
/* otherwise we extract the info from the CFF glyphstrings */
/* (instead of synthesizing a global value using the `OS/2' */
@@ -232,6 +243,13 @@
}
else
{
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* no fast retrieval for blended MM fonts without HVAR table */
+ if ( !ttface->is_default_instance &&
+ !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+ return FT_THROW( Unimplemented_Feature );
+#endif
+
/* check whether we have data from the `hmtx' table at all */
if ( !ttface->horizontal.number_Of_HMetrics )
goto Missing_Table;
@@ -291,6 +309,35 @@
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 )
{
FT_ERROR(( "cff_get_glyph_name:"
@@ -332,6 +379,31 @@
cff = (CFF_FontRec *)face->extra.data;
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 );
if ( !psnames )
return 0;
@@ -358,8 +430,9 @@
FT_DEFINE_SERVICE_GLYPHDICTREC(
cff_service_glyph_dict,
- (FT_GlyphDict_GetNameFunc) cff_get_glyph_name,
- (FT_GlyphDict_NameIndexFunc)cff_get_name_index
+
+ (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, /* get_name */
+ (FT_GlyphDict_NameIndexFunc)cff_get_name_index /* name_index */
)
@@ -383,11 +456,11 @@
FT_Error error = FT_Err_Ok;
- if ( cff && cff->font_info == NULL )
+ if ( cff && !cff->font_info )
{
- CFF_FontRecDict dict = &cff->top_font.font_dict;
+ CFF_FontRecDict dict = &cff->top_font.font_dict;
PS_FontInfoRec *font_info = NULL;
- FT_Memory memory = face->root.memory;
+ FT_Memory memory = face->root.memory;
if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
@@ -421,11 +494,14 @@
FT_DEFINE_SERVICE_PSINFOREC(
cff_service_ps_info,
- (PS_GetFontInfoFunc) cff_ps_get_font_info,
- (PS_GetFontExtraFunc) NULL,
- (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
- (PS_GetFontPrivateFunc)NULL, /* unsupported with CFF fonts */
- (PS_GetFontValueFunc) NULL /* not implemented */
+
+ (PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */
+ (PS_GetFontExtraFunc) NULL, /* ps_get_font_extra */
+ (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, /* ps_has_glyph_names */
+ /* unsupported with CFF fonts */
+ (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */
+ /* not implemented */
+ (PS_GetFontValueFunc) NULL /* ps_get_font_value */
)
@@ -444,14 +520,15 @@
/* following the OpenType specification 1.7, we return the name stored */
/* in the `name' table for a CFF wrapped into an SFNT container */
- if ( sfnt )
+ if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt )
{
FT_Library library = FT_FACE_LIBRARY( face );
FT_Module sfnt_module = FT_Get_Module( library, "sfnt" );
FT_Service_PsFontName service =
(FT_Service_PsFontName)ft_module_get_service(
sfnt_module,
- FT_SERVICE_ID_POSTSCRIPT_FONT_NAME );
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME,
+ 0 );
if ( service && service->get_ps_font_name )
@@ -464,7 +541,8 @@
FT_DEFINE_SERVICE_PSFONTNAMEREC(
cff_service_ps_name,
- (FT_PsName_GetFunc)cff_get_ps_name
+
+ (FT_PsName_GetFunc)cff_get_ps_name /* get_ps_font_name */
)
@@ -489,21 +567,21 @@
FT_Library library = FT_FACE_LIBRARY( face );
- cmap_info->language = 0;
- cmap_info->format = 0;
-
if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET )
{
FT_Module sfnt = FT_Get_Module( library, "sfnt" );
FT_Service_TTCMaps service =
(FT_Service_TTCMaps)ft_module_get_service( sfnt,
- FT_SERVICE_ID_TT_CMAP );
+ FT_SERVICE_ID_TT_CMAP,
+ 0 );
if ( service && service->get_cmap_info )
error = service->get_cmap_info( charmap, cmap_info );
}
+ else
+ error = FT_THROW( Invalid_CharMap_Format );
return error;
}
@@ -511,7 +589,8 @@
FT_DEFINE_SERVICE_TTCMAPSREC(
cff_service_get_cmap_info,
- (TT_CMap_Info_GetFunc)cff_get_cmap_info
+
+ (TT_CMap_Info_GetFunc)cff_get_cmap_info /* get_cmap_info */
)
@@ -542,7 +621,7 @@
if ( registry )
{
- if ( cff->registry == NULL )
+ if ( !cff->registry )
cff->registry = cff_index_get_sid_string( cff,
dict->cid_registry );
*registry = cff->registry;
@@ -550,7 +629,7 @@
if ( ordering )
{
- if ( cff->ordering == NULL )
+ if ( !cff->ordering )
cff->ordering = cff_index_get_sid_string( cff,
dict->cid_ordering );
*ordering = cff->ordering;
@@ -641,9 +720,13 @@
FT_DEFINE_SERVICE_CIDREC(
cff_service_cid_info,
- (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
- (FT_CID_GetIsInternallyCIDKeyedFunc) cff_get_is_cid,
- (FT_CID_GetCIDFromGlyphIndexFunc) cff_get_cid_from_glyph_index
+
+ (FT_CID_GetRegistryOrderingSupplementFunc)
+ cff_get_ros, /* get_ros */
+ (FT_CID_GetIsInternallyCIDKeyedFunc)
+ cff_get_is_cid, /* get_is_cid */
+ (FT_CID_GetCIDFromGlyphIndexFunc)
+ cff_get_cid_from_glyph_index /* get_cid_from_glyph_index */
)
@@ -654,26 +737,62 @@
static FT_Error
cff_property_set( FT_Module module, /* CFF_Driver */
const char* property_name,
- const void* value )
+ const void* value,
+ FT_Bool value_is_string )
{
FT_Error error = FT_Err_Ok;
CFF_Driver driver = (CFF_Driver)module;
+#ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ FT_UNUSED( value_is_string );
+#endif
+
if ( !ft_strcmp( property_name, "darkening-parameters" ) )
{
- FT_Int* darken_params = (FT_Int*)value;
+ FT_Int* darken_params;
+ FT_Int x1, y1, x2, y2, x3, y3, x4, y4;
- FT_Int x1 = darken_params[0];
- FT_Int y1 = darken_params[1];
- FT_Int x2 = darken_params[2];
- FT_Int y2 = darken_params[3];
- FT_Int x3 = darken_params[4];
- FT_Int y3 = darken_params[5];
- FT_Int x4 = darken_params[6];
- FT_Int y4 = darken_params[7];
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ FT_Int dp[8];
+ if ( value_is_string )
+ {
+ const char* s = (const char*)value;
+ char* ep;
+ int i;
+
+
+ /* eight comma-separated numbers */
+ for ( i = 0; i < 7; i++ )
+ {
+ dp[i] = (FT_Int)ft_strtol( s, &ep, 10 );
+ if ( *ep != ',' || s == ep )
+ return FT_THROW( Invalid_Argument );
+
+ s = ep + 1;
+ }
+
+ dp[7] = (FT_Int)ft_strtol( s, &ep, 10 );
+ if ( !( *ep == '\0' || *ep == ' ' ) || s == ep )
+ return FT_THROW( Invalid_Argument );
+
+ darken_params = dp;
+ }
+ else
+#endif
+ darken_params = (FT_Int*)value;
+
+ x1 = darken_params[0];
+ y1 = darken_params[1];
+ x2 = darken_params[2];
+ y2 = darken_params[3];
+ x3 = darken_params[4];
+ y3 = darken_params[5];
+ x4 = darken_params[6];
+ y4 = darken_params[7];
+
if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
x1 > x2 || x2 > x3 || x3 > x4 ||
@@ -693,24 +812,62 @@
}
else if ( !ft_strcmp( property_name, "hinting-engine" ) )
{
- FT_UInt* hinting_engine = (FT_UInt*)value;
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ if ( value_is_string )
+ {
+ const char* s = (const char*)value;
-#ifndef CFF_CONFIG_OPTION_OLD_ENGINE
- if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
- error = FT_ERR( Unimplemented_Feature );
+ if ( !ft_strcmp( s, "adobe" ) )
+ driver->hinting_engine = FT_CFF_HINTING_ADOBE;
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ else if ( !ft_strcmp( s, "freetype" ) )
+ driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
+#endif
+ else
+ return FT_THROW( Invalid_Argument );
+ }
else
#endif
- driver->hinting_engine = *hinting_engine;
+ {
+ FT_UInt* hinting_engine = (FT_UInt*)value;
- return error;
+ if ( *hinting_engine == FT_CFF_HINTING_ADOBE
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ || *hinting_engine == FT_CFF_HINTING_FREETYPE
+#endif
+ )
+ driver->hinting_engine = *hinting_engine;
+ else
+ error = FT_ERR( Unimplemented_Feature );
+
+ return error;
+ }
}
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
{
- FT_Bool* no_stem_darkening = (FT_Bool*)value;
+#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+ if ( value_is_string )
+ {
+ const char* s = (const char*)value;
+ long nsd = ft_strtol( s, NULL, 10 );
+
+
+ if ( nsd == 0 )
+ driver->no_stem_darkening = 0;
+ else if ( nsd == 1 )
+ driver->no_stem_darkening = 1;
+ else
+ return FT_THROW( Invalid_Argument );
+ }
+ else
+#endif
+ {
+ FT_Bool* no_stem_darkening = (FT_Bool*)value;
- driver->no_stem_darkening = *no_stem_darkening;
+ driver->no_stem_darkening = *no_stem_darkening;
+ }
return error;
}
@@ -776,8 +933,92 @@
FT_DEFINE_SERVICE_PROPERTIESREC(
cff_service_properties,
- (FT_Properties_SetFunc)cff_property_set,
- (FT_Properties_GetFunc)cff_property_get )
+
+ (FT_Properties_SetFunc)cff_property_set, /* set_property */
+ (FT_Properties_GetFunc)cff_property_get ) /* get_property */
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+ /*
+ * MULTIPLE MASTER SERVICE
+ *
+ */
+
+ static FT_Error
+ cff_set_mm_blend( CFF_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ return mm->set_mm_blend( FT_FACE( face ), num_coords, coords );
+ }
+
+
+ static FT_Error
+ cff_get_mm_blend( CFF_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ return mm->get_mm_blend( FT_FACE( face ), num_coords, coords );
+ }
+
+
+ static FT_Error
+ cff_get_mm_var( CFF_Face face,
+ FT_MM_Var* *master )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ return mm->get_mm_var( FT_FACE( face ), master );
+ }
+
+
+ static FT_Error
+ cff_set_var_design( CFF_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ return mm->set_var_design( FT_FACE( face ), num_coords, coords );
+ }
+
+
+ static FT_Error
+ cff_get_var_design( CFF_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ return mm->get_var_design( FT_FACE( face ), num_coords, coords );
+ }
+
+
+ FT_DEFINE_SERVICE_MULTIMASTERSREC(
+ cff_service_multi_masters,
+
+ (FT_Get_MM_Func) NULL, /* get_mm */
+ (FT_Set_MM_Design_Func) NULL, /* set_mm_design */
+ (FT_Set_MM_Blend_Func) cff_set_mm_blend, /* set_mm_blend */
+ (FT_Get_MM_Blend_Func) cff_get_mm_blend, /* get_mm_blend */
+ (FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */
+ (FT_Set_Var_Design_Func)cff_set_var_design, /* set_var_design */
+ (FT_Get_Var_Design_Func)cff_get_var_design, /* get_var_design */
+
+ (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */
+ (FT_Done_Blend_Func) cff_done_blend /* done_blend */
+ )
+#endif
/*************************************************************************/
@@ -792,9 +1033,24 @@
/*************************************************************************/
/*************************************************************************/
-#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
+#if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \
+ defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ FT_DEFINE_SERVICEDESCREC8(
+ cff_services,
+
+ FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
+ FT_SERVICE_ID_MULTI_MASTERS, &CFF_SERVICE_MULTI_MASTERS_GET,
+ FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
+ FT_SERVICE_ID_GLYPH_DICT, &CFF_SERVICE_GLYPH_DICT_GET,
+ FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
+ FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
+ FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET
+ )
+#elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES
FT_DEFINE_SERVICEDESCREC7(
cff_services,
+
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
@@ -803,9 +1059,22 @@
FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET
)
+#elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ FT_DEFINE_SERVICEDESCREC7(
+ cff_services,
+
+ FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
+ FT_SERVICE_ID_MULTI_MASTERS, &CFF_SERVICE_MULTI_MASTERS_GET,
+ FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
+ FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
+ FT_SERVICE_ID_TT_CMAP, &CFF_SERVICE_GET_CMAP_INFO_GET,
+ FT_SERVICE_ID_CID, &CFF_SERVICE_CID_INFO_GET,
+ FT_SERVICE_ID_PROPERTIES, &CFF_SERVICE_PROPERTIES_GET
+ )
#else
FT_DEFINE_SERVICEDESCREC6(
cff_services,
+
FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF,
FT_SERVICE_ID_POSTSCRIPT_INFO, &CFF_SERVICE_PS_INFO_GET,
FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
@@ -835,7 +1104,7 @@
#endif
result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
- if ( result != NULL )
+ if ( result )
return result;
/* `driver' is not yet evaluated in non-PIC mode */
@@ -865,42 +1134,41 @@
FT_DEFINE_DRIVER(
cff_driver_class,
- FT_MODULE_FONT_DRIVER |
- FT_MODULE_DRIVER_SCALABLE |
- FT_MODULE_DRIVER_HAS_HINTER,
+ FT_MODULE_FONT_DRIVER |
+ FT_MODULE_DRIVER_SCALABLE |
+ FT_MODULE_DRIVER_HAS_HINTER |
+ FT_MODULE_DRIVER_HINTS_LIGHTLY,
sizeof ( CFF_DriverRec ),
"cff",
0x10000L,
0x20000L,
- 0, /* module-specific interface */
+ NULL, /* module-specific interface */
- cff_driver_init,
- cff_driver_done,
- cff_get_interface,
+ cff_driver_init, /* FT_Module_Constructor module_init */
+ cff_driver_done, /* FT_Module_Destructor module_done */
+ cff_get_interface, /* FT_Module_Requester get_interface */
- /* now the specific driver fields */
sizeof ( TT_FaceRec ),
sizeof ( CFF_SizeRec ),
sizeof ( CFF_GlyphSlotRec ),
- cff_face_init,
- cff_face_done,
- cff_size_init,
- cff_size_done,
- cff_slot_init,
- cff_slot_done,
-
- cff_glyph_load,
+ cff_face_init, /* FT_Face_InitFunc init_face */
+ cff_face_done, /* FT_Face_DoneFunc done_face */
+ cff_size_init, /* FT_Size_InitFunc init_size */
+ cff_size_done, /* FT_Size_DoneFunc done_size */
+ cff_slot_init, /* FT_Slot_InitFunc init_slot */
+ cff_slot_done, /* FT_Slot_DoneFunc done_slot */
- cff_get_kerning,
- 0, /* FT_Face_AttachFunc */
- cff_get_advances,
+ cff_glyph_load, /* FT_Slot_LoadFunc load_glyph */
- cff_size_request,
+ cff_get_kerning, /* FT_Face_GetKerningFunc get_kerning */
+ NULL, /* FT_Face_AttachFunc attach_file */
+ cff_get_advances, /* FT_Face_GetAdvancesFunc get_advances */
- CFF_SIZE_SELECT
+ cff_size_request, /* FT_Size_RequestFunc request_size */
+ CFF_SIZE_SELECT /* FT_Size_SelectFunc select_size */
)
diff --git a/third_party/freetype/src/cff/cffdrivr.h b/third_party/freetype/src/cff/cffdrivr.h
index 9527f5e149..05381e66db 100644
--- a/third_party/freetype/src/cff/cffdrivr.h
+++ b/third_party/freetype/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
/* */
/* High-level OpenType driver interface (specification). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,8 +16,8 @@
/***************************************************************************/
-#ifndef __CFFDRIVER_H__
-#define __CFFDRIVER_H__
+#ifndef CFFDRIVER_H_
+#define CFFDRIVER_H_
#include <ft2build.h>
@@ -32,7 +32,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CFFDRIVER_H__ */
+#endif /* CFFDRIVER_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cfferrs.h b/third_party/freetype/src/cff/cfferrs.h
index 543bdb07c2..40808c1051 100644
--- a/third_party/freetype/src/cff/cfferrs.h
+++ b/third_party/freetype/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
/* */
/* CFF error codes (specification only). */
/* */
-/* Copyright 2001-2015 by */
+/* Copyright 2001-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -22,12 +22,12 @@
/* */
/*************************************************************************/
-#ifndef __CFFERRS_H__
-#define __CFFERRS_H__
+#ifndef CFFERRS_H_
+#define CFFERRS_H_
#include FT_MODULE_ERRORS_H
-#undef __FTERRORS_H__
+#undef FTERRORS_H_
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX CFF_Err_
@@ -36,7 +36,7 @@
#include FT_ERRORS_H
-#endif /* __CFFERRS_H__ */
+#endif /* CFFERRS_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cffgload.c b/third_party/freetype/src/cff/cffgload.c
index 5f57403e22..f8e80c100d 100644
--- a/third_party/freetype/src/cff/cffgload.c
+++ b/third_party/freetype/src/cff/cffgload.c
@@ -4,7 +4,7 @@
/* */
/* OpenType Glyph Loader (body). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -391,7 +391,7 @@
/* clear everything */
- FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
+ FT_ZERO( decoder );
/* initialize builder */
cff_builder_init( &decoder->builder, face, size, slot, hinting );
@@ -680,7 +680,7 @@
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
{
- CFF_Font cff = (CFF_Font)(face->extra.data);
+ CFF_Font cff = (CFF_Font)(face->extra.data);
return cff_index_access_element( &cff->charstrings_index, glyph_index,
@@ -826,7 +826,7 @@
/* the seac operator must not be nested */
decoder->seac = TRUE;
error = cff_decoder_parse_charstrings( decoder, charstring,
- charstring_len );
+ charstring_len, 0 );
decoder->seac = FALSE;
cff_free_glyph_data( face, &charstring, charstring_len );
@@ -856,7 +856,7 @@
/* the seac operator must not be nested */
decoder->seac = TRUE;
error = cff_decoder_parse_charstrings( decoder, charstring,
- charstring_len );
+ charstring_len, 0 );
decoder->seac = FALSE;
cff_free_glyph_data( face, &charstring, charstring_len );
@@ -895,13 +895,17 @@
/* */
/* charstring_len :: The length in bytes of the charstring stream. */
/* */
+ /* in_dict :: Set to 1 if function is called from top or */
+ /* private DICT (needed for Multiple Master CFFs). */
+ /* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
cff_decoder_parse_charstrings( CFF_Decoder* decoder,
FT_Byte* charstring_base,
- FT_ULong charstring_len )
+ FT_ULong charstring_len,
+ FT_Bool in_dict )
{
FT_Error error;
CFF_Decoder_Zone* zone;
@@ -913,6 +917,10 @@
FT_Fixed* stack;
FT_Int charstring_type =
decoder->cff->top_font.font_dict.charstring_type;
+ FT_UShort num_designs =
+ decoder->cff->top_font.font_dict.num_designs;
+ FT_UShort num_axes =
+ decoder->cff->top_font.font_dict.num_axes;
T2_Hints_Funcs hinter;
@@ -1018,7 +1026,7 @@
if ( !( val & 0xFFFFL ) )
FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) ));
else
- FT_TRACE4(( " %.2f", val / 65536.0 ));
+ FT_TRACE4(( " %.5f", val / 65536.0 ));
#endif
}
@@ -1241,6 +1249,44 @@
if ( op == cff_op_unknown )
continue;
+ /* in Multiple Master CFFs, T2 charstrings can appear in */
+ /* dictionaries, but some operators are prohibited */
+ if ( in_dict )
+ {
+ switch ( op )
+ {
+ case cff_op_hstem:
+ case cff_op_vstem:
+ case cff_op_vmoveto:
+ case cff_op_rlineto:
+ case cff_op_hlineto:
+ case cff_op_vlineto:
+ case cff_op_rrcurveto:
+ case cff_op_hstemhm:
+ case cff_op_hintmask:
+ case cff_op_cntrmask:
+ case cff_op_rmoveto:
+ case cff_op_hmoveto:
+ case cff_op_vstemhm:
+ case cff_op_rcurveline:
+ case cff_op_rlinecurve:
+ case cff_op_vvcurveto:
+ case cff_op_hhcurveto:
+ case cff_op_vhcurveto:
+ case cff_op_hvcurveto:
+ case cff_op_hflex:
+ case cff_op_flex:
+ case cff_op_hflex1:
+ case cff_op_flex1:
+ case cff_op_callsubr:
+ case cff_op_callgsubr:
+ goto MM_Error;
+
+ default:
+ break;
+ }
+ }
+
/* check arguments */
req_args = cff_argument_counts[op];
if ( req_args & CFF_COUNT_CHECK_WIDTH )
@@ -1278,7 +1324,9 @@
case cff_op_endchar:
/* If there is a width specified for endchar, we either have */
/* 1 argument or 5 arguments. We like to argue. */
- set_width_ok = ( num_args == 5 ) || ( num_args == 1 );
+ set_width_ok = in_dict
+ ? 0
+ : ( ( num_args == 5 ) || ( num_args == 1 ) );
break;
default:
@@ -1971,6 +2019,10 @@
return error;
case cff_op_endchar:
+ /* in dictionaries, `endchar' simply indicates end of data */
+ if ( in_dict )
+ return error;
+
FT_TRACE4(( " endchar\n" ));
/* We are going to emulate the seac operator. */
@@ -2082,15 +2134,14 @@
if ( args[0] > 0 )
{
- FT_Int count = 9;
- FT_Fixed root = args[0];
+ FT_Fixed root = args[0];
FT_Fixed new_root;
for (;;)
{
new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
- if ( new_root == root || count <= 0 )
+ if ( new_root == root )
break;
root = new_root;
}
@@ -2199,6 +2250,10 @@
FT_TRACE4(( " put\n" ));
+ /* the Type2 specification before version 16-March-2000 */
+ /* didn't give a hard-coded size limit of the temporary */
+ /* storage array; instead, an argument of the */
+ /* `MultipleMaster' operator set the size */
if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
decoder->buildchar[idx] = val;
}
@@ -2221,14 +2276,68 @@
break;
case cff_op_store:
- FT_TRACE4(( " store\n"));
+ /* this operator was removed from the Type2 specification */
+ /* in version 16-March-2000 */
- goto Unimplemented;
+ /* since we currently don't handle interpolation of multiple */
+ /* master fonts, this is a no-op */
+ FT_TRACE4(( " store\n"));
+ break;
case cff_op_load:
- FT_TRACE4(( " load\n" ));
+ /* this operator was removed from the Type2 specification */
+ /* in version 16-March-2000 */
+ {
+ FT_Int reg_idx = (FT_Int)args[0];
+ FT_Int idx = (FT_Int)args[1];
+ FT_Int count = (FT_Int)args[2];
+
+
+ FT_TRACE4(( " load\n" ));
+
+ /* since we currently don't handle interpolation of multiple */
+ /* master fonts, we store a vector [1 0 0 ...] in the */
+ /* temporary storage array regardless of the Registry index */
+ if ( reg_idx >= 0 && reg_idx <= 2 &&
+ idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS &&
+ count >= 0 && count <= num_axes )
+ {
+ FT_Int end, i;
+
+
+ end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS );
+
+ if ( idx < end )
+ decoder->buildchar[idx] = 1 << 16;
+
+ for ( i = idx + 1; i < end; i++ )
+ decoder->buildchar[i] = 0;
+ }
+ }
+ break;
- goto Unimplemented;
+ case cff_op_blend:
+ /* this operator was removed from the Type2 specification */
+ /* in version 16-March-2000 */
+ {
+ FT_Int num_results = (FT_Int)( args[0] >> 16 );
+
+
+ FT_TRACE4(( " blend\n" ));
+
+ if ( num_results < 0 )
+ goto Syntax_Error;
+
+ if ( num_results * (FT_Int)num_designs > num_args )
+ goto Stack_Underflow;
+
+ /* since we currently don't handle interpolation of multiple */
+ /* master fonts, return the `num_results' values of the */
+ /* first master */
+ args -= num_results * ( num_designs - 1 );
+ num_args -= num_results * ( num_designs - 1 );
+ }
+ break;
case cff_op_dotsection:
/* this operator is deprecated and ignored by the parser */
@@ -2336,7 +2445,7 @@
case cff_op_and:
{
- FT_Fixed cond = args[0] && args[1];
+ FT_Fixed cond = ( args[0] && args[1] );
FT_TRACE4(( " and\n" ));
@@ -2348,7 +2457,7 @@
case cff_op_or:
{
- FT_Fixed cond = args[0] || args[1];
+ FT_Fixed cond = ( args[0] || args[1] );
FT_TRACE4(( " or\n" ));
@@ -2358,11 +2467,23 @@
}
break;
- case cff_op_eq:
+ case cff_op_not:
{
FT_Fixed cond = !args[0];
+ FT_TRACE4(( " not\n" ));
+
+ args[0] = cond ? 0x10000L : 0;
+ args++;
+ }
+ break;
+
+ case cff_op_eq:
+ {
+ FT_Fixed cond = ( args[0] == args[1] );
+
+
FT_TRACE4(( " eq\n" ));
args[0] = cond ? 0x10000L : 0;
@@ -2489,7 +2610,6 @@
break;
default:
- Unimplemented:
FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
if ( ip[-1] == 12 )
@@ -2513,6 +2633,11 @@
Fail:
return error;
+ MM_Error:
+ FT_TRACE4(( "cff_decoder_parse_charstrings:"
+ " invalid opcode found in top DICT charstring\n"));
+ return FT_THROW( Invalid_File_Format );
+
Syntax_Error:
FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
return FT_THROW( Invalid_File_Format );
@@ -2586,7 +2711,8 @@
if ( !error )
error = cff_decoder_parse_charstrings( &decoder,
charstring,
- charstring_len );
+ charstring_len,
+ 0 );
cff_free_glyph_data( face, &charstring, &charstring_len );
}
@@ -2816,6 +2942,7 @@
cff_decoder_init( &decoder, face, size, glyph, hinting,
FT_LOAD_TARGET_MODE( load_flags ) );
+ /* this is for pure CFFs */
if ( load_flags & FT_LOAD_ADVANCE_ONLY )
decoder.width_only = TRUE;
@@ -2837,7 +2964,8 @@
if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
error = cff_decoder_parse_charstrings( &decoder,
charstring,
- charstring_len );
+ charstring_len,
+ 0 );
else
#endif
{
diff --git a/third_party/freetype/src/cff/cffgload.h b/third_party/freetype/src/cff/cffgload.h
index 5f2655f3d9..0fa93b4398 100644
--- a/third_party/freetype/src/cff/cffgload.h
+++ b/third_party/freetype/src/cff/cffgload.h
@@ -4,7 +4,7 @@
/* */
/* OpenType Glyph Loader (specification). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,8 +16,8 @@
/***************************************************************************/
-#ifndef __CFFGLOAD_H__
-#define __CFFGLOAD_H__
+#ifndef CFFGLOAD_H_
+#define CFFGLOAD_H_
#include <ft2build.h>
@@ -227,7 +227,8 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
cff_decoder_parse_charstrings( CFF_Decoder* decoder,
FT_Byte* charstring_base,
- FT_ULong charstring_len );
+ FT_ULong charstring_len,
+ FT_Bool in_dict );
#endif
FT_LOCAL( FT_Error )
@@ -239,7 +240,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CFFGLOAD_H__ */
+#endif /* CFFGLOAD_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cffload.c b/third_party/freetype/src/cff/cffload.c
index c61222d651..935e612a09 100644
--- a/third_party/freetype/src/cff/cffload.c
+++ b/third_party/freetype/src/cff/cffload.c
@@ -4,7 +4,7 @@
/* */
/* OpenType and CFF data/program tables loader (body). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,12 +23,20 @@
#include FT_TRUETYPE_TAGS_H
#include FT_TYPE1_TABLES_H
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#include FT_MULTIPLE_MASTERS_H
+#include FT_SERVICE_MULTIPLE_MASTERS_H
+#endif
+
#include "cffload.h"
#include "cffparse.h"
#include "cfferrs.h"
+#define FT_FIXED_ONE ( (FT_Fixed)0x10000 )
+
+
#if 1
static const FT_UShort cff_isoadobe_charset[229] =
@@ -225,19 +233,33 @@
static FT_Error
cff_index_init( CFF_Index idx,
FT_Stream stream,
- FT_Bool load )
+ FT_Bool load,
+ FT_Bool cff2 )
{
FT_Error error;
FT_Memory memory = stream->memory;
- FT_UShort count;
+ FT_UInt count;
- FT_MEM_ZERO( idx, sizeof ( *idx ) );
+ FT_ZERO( idx );
idx->stream = stream;
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_ULong size;
@@ -258,7 +280,7 @@
idx->off_size = 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 ) )
goto Exit;
@@ -310,7 +332,7 @@
FT_FRAME_RELEASE( idx->bytes );
FT_FREE( idx->offsets );
- FT_MEM_ZERO( idx, sizeof ( *idx ) );
+ FT_ZERO( idx );
}
}
@@ -323,7 +345,7 @@
FT_Memory memory = stream->memory;
- if ( idx->count > 0 && idx->offsets == NULL )
+ if ( idx->count > 0 && !idx->offsets )
{
FT_Byte offsize = idx->off_size;
FT_ULong data_size;
@@ -335,7 +357,7 @@
data_size = (FT_ULong)( idx->count + 1 ) * offsize;
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 ) )
goto Exit;
@@ -382,28 +404,31 @@
static FT_Error
cff_index_get_pointers( CFF_Index idx,
FT_Byte*** table,
- FT_Byte** pool )
+ FT_Byte** pool,
+ FT_ULong* pool_size )
{
FT_Error error = FT_Err_Ok;
FT_Memory memory = idx->stream->memory;
FT_Byte** t = NULL;
FT_Byte* new_bytes = NULL;
+ FT_ULong new_size;
*table = NULL;
- if ( idx->offsets == NULL )
+ if ( !idx->offsets )
{
error = cff_index_load_offsets( idx );
if ( error )
goto Exit;
}
- if ( idx->count > 0 &&
- !FT_NEW_ARRAY( t, idx->count + 1 ) &&
- ( !pool || !FT_ALLOC( new_bytes,
- idx->data_size + idx->count ) ) )
+ new_size = idx->data_size + idx->count;
+
+ if ( idx->count > 0 &&
+ !FT_NEW_ARRAY( t, idx->count + 1 ) &&
+ ( !pool || !FT_ALLOC( new_bytes, new_size ) ) )
{
FT_ULong n, cur_offset;
FT_ULong extra = 0;
@@ -459,6 +484,8 @@
if ( pool )
*pool = new_bytes;
+ if ( pool_size )
+ *pool_size = new_size;
}
Exit:
@@ -488,7 +515,7 @@
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;
off1 = cff_index_read_offset( idx, &error );
@@ -501,8 +528,8 @@
{
element++;
off2 = cff_index_read_offset( idx, &error );
- }
- while ( off2 == 0 && element < idx->count );
+
+ } while ( off2 == 0 && element < idx->count );
}
}
else /* use offsets table */
@@ -584,20 +611,26 @@
FT_UInt element )
{
CFF_Index idx = &font->name_index;
- FT_Memory memory = idx->stream->memory;
+ FT_Memory memory;
FT_Byte* bytes;
FT_ULong byte_len;
FT_Error error;
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 );
if ( error )
goto Exit;
if ( !FT_ALLOC( name, byte_len + 1 ) )
{
- FT_MEM_COPY( name, bytes, byte_len );
+ if ( byte_len )
+ FT_MEM_COPY( name, bytes, byte_len );
name[byte_len] = 0;
}
cff_index_forget_element( idx, &bytes );
@@ -719,6 +752,11 @@
FT_Byte fd = 0;
+ /* if there is no FDSelect, return zero */
+ /* Note: CFF2 with just one Font Dict has no FDSelect */
+ if ( !fdselect->data )
+ goto Exit;
+
switch ( fdselect->format )
{
case 0:
@@ -771,6 +809,7 @@
;
}
+ Exit:
return fd;
}
@@ -809,7 +848,7 @@
/* When multiple GIDs map to the same CID, we choose the lowest */
/* GID. This is not described in any spec, but it matches the */
/* behaviour of recent Acroread versions. */
- for ( j = (FT_Long)num_glyphs - 1; j >= 0 ; j-- )
+ for ( j = (FT_Long)num_glyphs - 1; j >= 0; j-- )
charset->cids[charset->sids[j]] = (FT_UShort)j;
charset->max_cid = max_cid;
@@ -871,8 +910,8 @@
FT_UShort glyph_sid;
- /* If the the offset is greater than 2, we have to parse the */
- /* charset table. */
+ /* If the offset is greater than 2, we have to parse the charset */
+ /* table. */
if ( offset > 2 )
{
FT_UInt j;
@@ -1049,6 +1088,512 @@
static void
+ cff_vstore_done( CFF_VStoreRec* vstore,
+ FT_Memory memory )
+ {
+ FT_UInt i;
+
+
+ /* free regionList and axisLists */
+ if ( vstore->varRegionList )
+ {
+ for ( i = 0; i < vstore->regionCount; i++ )
+ FT_FREE( vstore->varRegionList[i].axisList );
+ }
+ FT_FREE( vstore->varRegionList );
+
+ /* free varData and indices */
+ if ( vstore->varData )
+ {
+ for ( i = 0; i < vstore->dataCount; i++ )
+ FT_FREE( vstore->varData[i].regionIndices );
+ }
+ FT_FREE( vstore->varData );
+ }
+
+
+ /* convert 2.14 to Fixed */
+ #define FT_fdot14ToFixed( x ) ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
+
+
+ static FT_Error
+ cff_vstore_load( CFF_VStoreRec* vstore,
+ FT_Stream stream,
+ FT_ULong base_offset,
+ FT_ULong offset )
+ {
+ FT_Memory memory = stream->memory;
+ FT_Error error = FT_ERR( Invalid_File_Format );
+
+ FT_ULong* dataOffsetArray = NULL;
+ FT_UInt i, j;
+
+
+ /* no offset means no vstore to parse */
+ if ( offset )
+ {
+ FT_UInt vsOffset;
+ FT_UInt format;
+ FT_ULong regionListOffset;
+
+
+ /* we need to parse the table to determine its size; */
+ /* skip table length */
+ if ( FT_STREAM_SEEK( base_offset + offset ) ||
+ FT_STREAM_SKIP( 2 ) )
+ goto Exit;
+
+ /* actual variation store begins after the length */
+ vsOffset = FT_STREAM_POS();
+
+ /* check the header */
+ if ( FT_READ_USHORT( format ) )
+ goto Exit;
+ if ( format != 1 )
+ {
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ /* read top level fields */
+ if ( FT_READ_ULONG( regionListOffset ) ||
+ FT_READ_USHORT( vstore->dataCount ) )
+ goto Exit;
+
+ /* make temporary copy of item variation data offsets; */
+ /* we'll parse region list first, then come back */
+ if ( FT_NEW_ARRAY( dataOffsetArray, vstore->dataCount ) )
+ goto Exit;
+
+ for ( i = 0; i < vstore->dataCount; i++ )
+ {
+ if ( FT_READ_ULONG( dataOffsetArray[i] ) )
+ goto Exit;
+ }
+
+ /* parse regionList and axisLists */
+ if ( FT_STREAM_SEEK( vsOffset + regionListOffset ) ||
+ FT_READ_USHORT( vstore->axisCount ) ||
+ FT_READ_USHORT( vstore->regionCount ) )
+ goto Exit;
+
+ if ( FT_NEW_ARRAY( vstore->varRegionList, vstore->regionCount ) )
+ goto Exit;
+
+ for ( i = 0; i < vstore->regionCount; i++ )
+ {
+ CFF_VarRegion* region = &vstore->varRegionList[i];
+
+
+ if ( FT_NEW_ARRAY( region->axisList, vstore->axisCount ) )
+ goto Exit;
+
+ for ( j = 0; j < vstore->axisCount; j++ )
+ {
+ CFF_AxisCoords* axis = &region->axisList[j];
+
+ FT_Int16 start14, peak14, end14;
+
+
+ if ( FT_READ_SHORT( start14 ) ||
+ FT_READ_SHORT( peak14 ) ||
+ FT_READ_SHORT( end14 ) )
+ goto Exit;
+
+ axis->startCoord = FT_fdot14ToFixed( start14 );
+ axis->peakCoord = FT_fdot14ToFixed( peak14 );
+ axis->endCoord = FT_fdot14ToFixed( end14 );
+ }
+ }
+
+ /* use dataOffsetArray now to parse varData items */
+ if ( FT_NEW_ARRAY( vstore->varData, vstore->dataCount ) )
+ goto Exit;
+
+ for ( i = 0; i < vstore->dataCount; i++ )
+ {
+ CFF_VarData* data = &vstore->varData[i];
+
+
+ if ( FT_STREAM_SEEK( vsOffset + dataOffsetArray[i] ) )
+ goto Exit;
+
+ /* ignore `itemCount' and `shortDeltaCount' */
+ /* because CFF2 has no delta sets */
+ if ( FT_STREAM_SKIP( 4 ) )
+ goto Exit;
+
+ /* Note: just record values; consistency is checked later */
+ /* by cff_blend_build_vector when it consumes `vstore' */
+
+ if ( FT_READ_USHORT( data->regionIdxCount ) )
+ goto Exit;
+
+ if ( FT_NEW_ARRAY( data->regionIndices, data->regionIdxCount ) )
+ goto Exit;
+
+ for ( j = 0; j < data->regionIdxCount; j++ )
+ {
+ if ( FT_READ_USHORT( data->regionIndices[j] ) )
+ goto Exit;
+ }
+ }
+ }
+
+ error = FT_Err_Ok;
+
+ Exit:
+ FT_FREE( dataOffsetArray );
+ if ( error )
+ cff_vstore_done( vstore, memory );
+
+ return error;
+ }
+
+
+ /* Clear blend stack (after blend values are consumed). */
+ /* */
+ /* TODO: Should do this in cff_run_parse, but subFont */
+ /* ref is not available there. */
+ /* */
+ /* Allocation is not changed when stack is cleared. */
+ FT_LOCAL_DEF( void )
+ cff_blend_clear( CFF_SubFont subFont )
+ {
+ subFont->blend_top = subFont->blend_stack;
+ subFont->blend_used = 0;
+ }
+
+
+ /* Blend numOperands on the stack, */
+ /* store results into the first numBlends values, */
+ /* then pop remaining arguments. */
+ /* */
+ /* This is comparable to `cf2_doBlend' but */
+ /* the cffparse stack is different and can't be written. */
+ /* Blended values are written to a different buffer, */
+ /* using reserved operator 255. */
+ /* */
+ /* Blend calculation is done in 16.16 fixed point. */
+ FT_LOCAL_DEF( FT_Error )
+ cff_blend_doBlend( CFF_SubFont subFont,
+ CFF_Parser parser,
+ FT_UInt numBlends )
+ {
+ FT_UInt delta;
+ FT_UInt base;
+ FT_UInt i, j;
+ FT_UInt size;
+
+ CFF_Blend blend = &subFont->blend;
+
+ FT_Memory memory = subFont->blend.font->memory; /* for FT_REALLOC */
+ FT_Error error = FT_Err_Ok; /* for FT_REALLOC */
+
+ /* compute expected number of operands for this blend */
+ FT_UInt numOperands = (FT_UInt)( numBlends * blend->lenBV );
+ FT_UInt count = (FT_UInt)( parser->top - 1 - parser->stack );
+
+
+ if ( numOperands > count )
+ {
+ FT_TRACE4(( " cff_blend_doBlend: Stack underflow %d args\n", count ));
+
+ error = FT_THROW( Stack_Underflow );
+ goto Exit;
+ }
+
+ /* check whether we have room for `numBlends' values at `blend_top' */
+ size = 5 * numBlends; /* add 5 bytes per entry */
+ if ( subFont->blend_used + size > subFont->blend_alloc )
+ {
+ FT_Byte* blend_stack_old = subFont->blend_stack;
+ FT_Byte* blend_top_old = subFont->blend_top;
+
+
+ /* increase or allocate `blend_stack' and reset `blend_top'; */
+ /* prepare to append `numBlends' values to the buffer */
+ if ( FT_REALLOC( subFont->blend_stack,
+ subFont->blend_alloc,
+ subFont->blend_alloc + size ) )
+ goto Exit;
+
+ subFont->blend_top = subFont->blend_stack + subFont->blend_used;
+ subFont->blend_alloc += size;
+
+ /* iterate over the parser stack and adjust pointers */
+ /* if the reallocated buffer has a different address */
+ if ( blend_stack_old &&
+ subFont->blend_stack != blend_stack_old )
+ {
+ FT_PtrDist offset = subFont->blend_stack - blend_stack_old;
+ FT_Byte** p;
+
+
+ for ( p = parser->stack; p < parser->top; p++ )
+ {
+ if ( *p >= blend_stack_old && *p < blend_top_old )
+ *p += offset;
+ }
+ }
+ }
+ subFont->blend_used += size;
+
+ base = count - numOperands; /* index of first blend arg */
+ delta = base + numBlends; /* index of first delta arg */
+
+ for ( i = 0; i < numBlends; i++ )
+ {
+ const FT_Int32* weight = &blend->BV[1];
+ FT_Int32 sum;
+
+
+ /* convert inputs to 16.16 fixed point */
+ sum = cff_parse_num( parser, &parser->stack[i + base] ) * 65536;
+
+ for ( j = 1; j < blend->lenBV; j++ )
+ sum += FT_MulFix( *weight++,
+ cff_parse_num( parser,
+ &parser->stack[delta++] ) * 65536 );
+
+ /* point parser stack to new value on blend_stack */
+ parser->stack[i + base] = subFont->blend_top;
+
+ /* Push blended result as Type 2 5-byte fixed point number. This */
+ /* will not conflict with actual DICTs because 255 is a reserved */
+ /* opcode in both CFF and CFF2 DICTs. See `cff_parse_num' for */
+ /* decode of this, which rounds to an integer. */
+ *subFont->blend_top++ = 255;
+ *subFont->blend_top++ = ( (FT_UInt32)sum & 0xFF000000U ) >> 24;
+ *subFont->blend_top++ = ( (FT_UInt32)sum & 0x00FF0000U ) >> 16;
+ *subFont->blend_top++ = ( (FT_UInt32)sum & 0x0000FF00U ) >> 8;
+ *subFont->blend_top++ = (FT_UInt32)sum & 0x000000FFU;
+ }
+
+ /* leave only numBlends results on parser stack */
+ parser->top = &parser->stack[base + numBlends];
+
+ Exit:
+ return error;
+ }
+
+
+ /* Compute a blend vector from variation store index and normalized */
+ /* vector based on pseudo-code in OpenType Font Variations Overview. */
+ /* */
+ /* Note: lenNDV == 0 produces a default blend vector, (1,0,0,...). */
+ FT_LOCAL_DEF( FT_Error )
+ cff_blend_build_vector( CFF_Blend blend,
+ FT_UInt vsindex,
+ FT_UInt lenNDV,
+ FT_Fixed* NDV )
+ {
+ FT_Error error = FT_Err_Ok; /* for FT_REALLOC */
+ FT_Memory memory = blend->font->memory; /* for FT_REALLOC */
+
+ FT_UInt len;
+ CFF_VStore vs;
+ CFF_VarData* varData;
+ FT_UInt master;
+
+
+ FT_ASSERT( lenNDV == 0 || NDV );
+
+ blend->builtBV = FALSE;
+
+ vs = &blend->font->vstore;
+
+ /* VStore and fvar must be consistent */
+ if ( lenNDV != 0 && lenNDV != vs->axisCount )
+ {
+ FT_TRACE4(( " cff_blend_build_vector: Axis count mismatch\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ if ( vsindex >= vs->dataCount )
+ {
+ FT_TRACE4(( " cff_blend_build_vector: vsindex out of range\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ /* select the item variation data structure */
+ varData = &vs->varData[vsindex];
+
+ /* prepare buffer for the blend vector */
+ len = varData->regionIdxCount + 1; /* add 1 for default component */
+ if ( FT_REALLOC( blend->BV,
+ blend->lenBV * sizeof( *blend->BV ),
+ len * sizeof( *blend->BV ) ) )
+ goto Exit;
+
+ blend->lenBV = len;
+
+ /* outer loop steps through master designs to be blended */
+ for ( master = 0; master < len; master++ )
+ {
+ FT_UInt j;
+ FT_UInt idx;
+ CFF_VarRegion* varRegion;
+
+
+ /* default factor is always one */
+ if ( master == 0 )
+ {
+ blend->BV[master] = FT_FIXED_ONE;
+ FT_TRACE4(( " build blend vector len %d\n"
+ " [ %f ",
+ len,
+ blend->BV[master] / 65536.0 ));
+ continue;
+ }
+
+ /* VStore array does not include default master, so subtract one */
+ idx = varData->regionIndices[master - 1];
+ varRegion = &vs->varRegionList[idx];
+
+ if ( idx >= vs->regionCount )
+ {
+ FT_TRACE4(( " cff_blend_build_vector:"
+ " region index out of range\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ /* Note: `lenNDV' could be zero. */
+ /* In that case, build default blend vector (1,0,0...). */
+ /* In the normal case, initialize each component to 1 */
+ /* before inner loop. */
+ if ( lenNDV != 0 )
+ blend->BV[master] = FT_FIXED_ONE; /* default */
+
+ /* inner loop steps through axes in this region */
+ for ( j = 0; j < lenNDV; j++ )
+ {
+ CFF_AxisCoords* axis = &varRegion->axisList[j];
+ FT_Fixed axisScalar;
+
+
+ /* compute the scalar contribution of this axis; */
+ /* ignore invalid ranges */
+ if ( axis->startCoord > axis->peakCoord ||
+ axis->peakCoord > axis->endCoord )
+ axisScalar = FT_FIXED_ONE;
+
+ else if ( axis->startCoord < 0 &&
+ axis->endCoord > 0 &&
+ axis->peakCoord != 0 )
+ axisScalar = FT_FIXED_ONE;
+
+ /* peak of 0 means ignore this axis */
+ else if ( axis->peakCoord == 0 )
+ axisScalar = FT_FIXED_ONE;
+
+ /* ignore this region if coords are out of range */
+ else if ( NDV[j] < axis->startCoord ||
+ NDV[j] > axis->endCoord )
+ axisScalar = 0;
+
+ /* calculate a proportional factor */
+ else
+ {
+ if ( NDV[j] == axis->peakCoord )
+ axisScalar = FT_FIXED_ONE;
+ else if ( NDV[j] < axis->peakCoord )
+ axisScalar = FT_DivFix( NDV[j] - axis->startCoord,
+ axis->peakCoord - axis->startCoord );
+ else
+ axisScalar = FT_DivFix( axis->endCoord - NDV[j],
+ axis->endCoord - axis->peakCoord );
+ }
+
+ /* take product of all the axis scalars */
+ blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar );
+ }
+
+ FT_TRACE4(( ", %f ",
+ blend->BV[master] / 65536.0 ));
+ }
+
+ FT_TRACE4(( "]\n" ));
+
+ /* record the parameters used to build the blend vector */
+ blend->lastVsindex = vsindex;
+
+ if ( lenNDV != 0 )
+ {
+ /* user has set a normalized vector */
+ if ( FT_REALLOC( blend->lastNDV,
+ blend->lenNDV * sizeof ( *NDV ),
+ lenNDV * sizeof ( *NDV ) ) )
+ goto Exit;
+
+ blend->lenNDV = lenNDV;
+ FT_MEM_COPY( blend->lastNDV,
+ NDV,
+ lenNDV * sizeof ( *NDV ) );
+ }
+
+ blend->builtBV = TRUE;
+
+ Exit:
+ return error;
+ }
+
+
+ /* `lenNDV' is zero for default vector; */
+ /* return TRUE if blend vector needs to be built. */
+ FT_LOCAL_DEF( FT_Bool )
+ cff_blend_check_vector( CFF_Blend blend,
+ FT_UInt vsindex,
+ FT_UInt lenNDV,
+ FT_Fixed* NDV )
+ {
+ if ( !blend->builtBV ||
+ blend->lastVsindex != vsindex ||
+ blend->lenNDV != lenNDV ||
+ ( lenNDV &&
+ memcmp( NDV,
+ blend->lastNDV,
+ lenNDV * sizeof ( *NDV ) ) != 0 ) )
+ {
+ /* need to build blend vector */
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+ FT_LOCAL_DEF( FT_Error )
+ cff_get_var_blend( CFF_Face face,
+ FT_UInt *num_coords,
+ FT_Fixed* *coords,
+ FT_MM_Var* *mm_var )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ return mm->get_var_blend( FT_FACE( face ), num_coords, coords, mm_var );
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cff_done_blend( CFF_Face face )
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+
+ mm->done_blend( FT_FACE( face ) );
+ }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+
+ static void
cff_encoding_done( CFF_Encoding encoding )
{
encoding->format = 0;
@@ -1300,26 +1845,127 @@
}
+ /* Parse private dictionary; first call is always from `cff_face_init', */
+ /* so NDV has not been set for CFF2 variation. */
+ /* */
+ /* `cff_slot_load' must call this function each time NDV changes. */
+ FT_LOCAL_DEF( FT_Error )
+ cff_load_private_dict( CFF_Font font,
+ CFF_SubFont subfont,
+ FT_UInt lenNDV,
+ FT_Fixed* NDV )
+ {
+ FT_Error error = FT_Err_Ok;
+ CFF_ParserRec parser;
+ CFF_FontRecDict top = &subfont->font_dict;
+ CFF_Private priv = &subfont->private_dict;
+ FT_Stream stream = font->stream;
+ FT_UInt stackSize;
+
+
+ /* store handle needed to access memory, vstore for blend; */
+ /* we need this for clean-up even if there is no private DICT */
+ subfont->blend.font = font;
+ subfont->blend.usedBV = FALSE; /* clear state */
+
+ if ( !top->private_offset || !top->private_size )
+ goto Exit2; /* no private DICT, do nothing */
+
+ /* set defaults */
+ FT_ZERO( priv );
+
+ priv->blue_shift = 7;
+ priv->blue_fuzz = 1;
+ priv->lenIV = -1;
+ priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
+ priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
+
+ /* provide inputs for blend calculations */
+ priv->subfont = subfont;
+ subfont->lenNDV = lenNDV;
+ subfont->NDV = NDV;
+
+ stackSize = font->cff2 ? font->top_font.font_dict.maxstack
+ : CFF_MAX_STACK_DEPTH + 1;
+
+ if ( cff_parser_init( &parser,
+ font->cff2 ? CFF2_CODE_PRIVATE : CFF_CODE_PRIVATE,
+ priv,
+ font->library,
+ stackSize,
+ top->num_designs,
+ top->num_axes ) )
+ goto Exit;
+
+ if ( FT_STREAM_SEEK( font->base_offset + top->private_offset ) ||
+ FT_FRAME_ENTER( top->private_size ) )
+ goto Exit;
+
+ FT_TRACE4(( " private dictionary:\n" ));
+ error = cff_parser_run( &parser,
+ (FT_Byte*)stream->cursor,
+ (FT_Byte*)stream->limit );
+ FT_FRAME_EXIT();
+
+ if ( error )
+ goto Exit;
+
+ /* ensure that `num_blue_values' is even */
+ priv->num_blue_values &= ~1;
+
+ Exit:
+ /* clean up */
+ cff_blend_clear( subfont ); /* clear blend stack */
+ cff_parser_done( &parser ); /* free parser stack */
+
+ Exit2:
+ /* no clean up (parser not initialized) */
+ return error;
+ }
+
+
+ /* 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
- cff_subfont_load( CFF_SubFont font,
+ cff_subfont_load( CFF_SubFont subfont,
CFF_Index idx,
FT_UInt font_index,
FT_Stream stream,
FT_ULong base_offset,
- FT_Library library )
+ FT_UInt code,
+ CFF_Font font )
{
FT_Error error;
CFF_ParserRec parser;
FT_Byte* dict = NULL;
FT_ULong dict_len;
- CFF_FontRecDict top = &font->font_dict;
- CFF_Private priv = &font->private_dict;
-
-
- cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
+ CFF_FontRecDict top = &subfont->font_dict;
+ CFF_Private priv = &subfont->private_dict;
+
+ FT_Bool cff2 = FT_BOOL( 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. */
+ error = cff_parser_init( &parser,
+ code,
+ &subfont->font_dict,
+ font->library,
+ stackSize,
+ 0,
+ 0 );
+ if ( error )
+ goto Exit;
/* set defaults */
- FT_MEM_ZERO( top, sizeof ( *top ) );
+ FT_ZERO( top );
top->underline_position = -( 100L << 16 );
top->underline_thickness = 50L << 16;
@@ -1342,14 +1988,35 @@
top->cid_ordering = 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 )
{
FT_TRACE4(( " top dictionary:\n" ));
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 )
goto Exit;
@@ -1358,35 +2025,14 @@
if ( top->cid_registry != 0xFFFFU )
goto Exit;
- /* parse the private dictionary, if any */
- if ( top->private_offset && top->private_size )
- {
- /* set defaults */
- FT_MEM_ZERO( priv, sizeof ( *priv ) );
-
- priv->blue_shift = 7;
- priv->blue_fuzz = 1;
- priv->lenIV = -1;
- priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
- priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
-
- cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
-
- if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
- FT_FRAME_ENTER( font->font_dict.private_size ) )
- goto Exit;
-
- FT_TRACE4(( " private dictionary:\n" ));
- error = cff_parser_run( &parser,
- (FT_Byte*)stream->cursor,
- (FT_Byte*)stream->limit );
- FT_FRAME_EXIT();
- if ( error )
- goto Exit;
-
- /* ensure that `num_blue_values' is even */
- priv->num_blue_values &= ~1;
- }
+ /* 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, 0, 0 );
+ if ( error )
+ goto Exit;
/* read the local subrs, if any */
if ( priv->local_subrs_offset )
@@ -1395,17 +2041,19 @@
priv->local_subrs_offset ) )
goto Exit;
- error = cff_index_init( &font->local_subrs_index, stream, 1 );
+ error = cff_index_init( &subfont->local_subrs_index, stream, 1, cff2 );
if ( error )
goto Exit;
- error = cff_index_get_pointers( &font->local_subrs_index,
- &font->local_subrs, NULL );
+ error = cff_index_get_pointers( &subfont->local_subrs_index,
+ &subfont->local_subrs, NULL, NULL );
if ( error )
goto Exit;
}
Exit:
+ cff_parser_done( &parser ); /* free parser stack */
+
return error;
}
@@ -1418,6 +2066,10 @@
{
cff_index_done( &subfont->local_subrs_index );
FT_FREE( subfont->local_subrs );
+
+ FT_FREE( subfont->blend.lastNDV );
+ FT_FREE( subfont->blend.BV );
+ FT_FREE( subfont->blend_stack );
}
}
@@ -1427,18 +2079,18 @@
FT_Stream stream,
FT_Int face_index,
CFF_Font font,
- FT_Bool pure_cff )
+ FT_Bool pure_cff,
+ FT_Bool cff2 )
{
static const FT_Frame_Field cff_header_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE CFF_FontRec
- FT_FRAME_START( 4 ),
+ FT_FRAME_START( 3 ),
FT_FRAME_BYTE( version_major ),
FT_FRAME_BYTE( version_minor ),
FT_FRAME_BYTE( header_size ),
- FT_FRAME_BYTE( absolute_offsize ),
FT_FRAME_END
};
@@ -1453,42 +2105,131 @@
FT_ZERO( font );
FT_ZERO( &string_index );
- font->stream = stream;
- font->memory = memory;
- dict = &font->top_font.font_dict;
- base_offset = FT_STREAM_POS();
+ dict = &font->top_font.font_dict;
+ base_offset = FT_STREAM_POS();
+
+ font->library = library;
+ font->stream = stream;
+ font->memory = memory;
+ font->cff2 = cff2;
+ font->base_offset = base_offset;
/* read CFF font header */
if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
goto Exit;
- /* check format */
- if ( font->version_major != 1 ||
- font->header_size < 4 ||
- font->absolute_offsize > 4 )
+ if ( cff2 )
{
- FT_TRACE2(( " not a CFF font header\n" ));
- error = FT_THROW( Unknown_File_Format );
- goto Exit;
+ if ( font->version_major != 2 ||
+ font->header_size < 5 )
+ {
+ 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
+ {
+ FT_Byte absolute_offset;
+
+
+ if ( FT_READ_BYTE( absolute_offset ) )
+ goto Exit;
+
+ if ( font->version_major != 1 ||
+ font->header_size < 4 ||
+ absolute_offset > 4 )
+ {
+ FT_TRACE2(( " not a CFF font header\n" ));
+ error = FT_THROW( Unknown_File_Format );
+ goto Exit;
+ }
}
/* skip the rest of the header */
- if ( FT_STREAM_SKIP( font->header_size - 4 ) )
+ if ( FT_STREAM_SEEK( base_offset + font->header_size ) )
+ {
+ /* For pure CFFs we have read only four bytes so far. Contrary to */
+ /* other formats like SFNT those bytes doesn't define a signature; */
+ /* it is thus possible that the font isn't a CFF at all. */
+ if ( pure_cff )
+ {
+ FT_TRACE2(( " not a CFF file\n" ));
+ error = FT_THROW( Unknown_File_Format );
+ }
goto Exit;
+ }
- /* read the name, top dict, string and global subrs index */
- if ( FT_SET_ERROR( cff_index_init( &font->name_index,
- stream, 0 ) ) ||
- FT_SET_ERROR( cff_index_init( &font->font_dict_index,
- stream, 0 ) ) ||
- FT_SET_ERROR( cff_index_init( &string_index,
- stream, 1 ) ) ||
- FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
- stream, 1 ) ) ||
- FT_SET_ERROR( cff_index_get_pointers( &string_index,
- &font->strings,
- &font->string_pool ) ) )
- goto Exit;
+ if ( cff2 )
+ {
+ /* For CFF2, the top dict data immediately follow the header */
+ /* and the length is stored in the header `offSize' field; */
+ /* there is no index for it. */
+ /* */
+ /* Use the `font_dict_index' to save the current position */
+ /* and length of data, but leave count at zero as an indicator. */
+ FT_ZERO( &font->font_dict_index );
+
+ font->font_dict_index.data_offset = FT_STREAM_POS();
+ font->font_dict_index.data_size = font->top_dict_length;
+
+ /* 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 ) ) )
+ {
+ if ( pure_cff )
+ {
+ FT_TRACE2(( " not a CFF file\n" ));
+ error = FT_THROW( Unknown_File_Format );
+ }
+ goto Exit;
+ }
+
+ /* font names must not be empty */
+ if ( font->name_index.data_size < font->name_index.count )
+ {
+ /* for pure CFFs, we still haven't checked enough bytes */
+ /* to be sure that it is a CFF at all */
+ error = pure_cff ? FT_THROW( Unknown_File_Format )
+ : FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ if ( 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;
+
+ /* there must be a Top DICT index entry for each name index entry */
+ if ( font->name_index.count > font->font_dict_index.count )
+ {
+ FT_ERROR(( "cff_font_load:"
+ " not enough entries in Top DICT index\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+ }
font->num_strings = string_index.count;
@@ -1534,34 +2275,47 @@
subfont_index,
stream,
base_offset,
- library );
+ cff2 ? CFF2_CODE_TOPDICT : CFF_CODE_TOPDICT,
+ font );
if ( error )
goto Exit;
if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
goto Exit;
- error = cff_index_init( &font->charstrings_index, stream, 0 );
+ error = cff_index_init( &font->charstrings_index, stream, 0, cff2 );
if ( error )
goto Exit;
- /* now, check for a CID font */
- if ( dict->cid_registry != 0xFFFFU )
+ /* now, check for a CID or CFF2 font */
+ if ( dict->cid_registry != 0xFFFFU ||
+ cff2 )
{
CFF_IndexRec fd_index;
CFF_SubFont sub = NULL;
FT_UInt idx;
+ /* for CFF2, read the Variation Store if available; */
+ /* this must follow the Top DICT parse and precede any Private DICT */
+ error = cff_vstore_load( &font->vstore,
+ stream,
+ base_offset,
+ dict->vstore_offset );
+ if ( error )
+ goto Exit;
+
/* this is a CID-keyed font, we must now allocate a table of */
/* sub-fonts, then load each of them separately */
if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
goto Exit;
- error = cff_index_init( &fd_index, stream, 0 );
+ error = cff_index_init( &fd_index, stream, 0, cff2 );
if ( error )
goto Exit;
+ /* Font Dicts are not limited to 256 for CFF2. */
+ /* TODO: support this for CFF2 */
if ( fd_index.count > CFF_MAX_CID_FONTS )
{
FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
@@ -1582,17 +2336,25 @@
{
sub = font->subfonts[idx];
FT_TRACE4(( "parsing subfont %u\n", idx ));
- error = cff_subfont_load( sub, &fd_index, idx,
- stream, base_offset, library );
+ error = cff_subfont_load( sub,
+ &fd_index,
+ idx,
+ stream,
+ base_offset,
+ cff2 ? CFF2_CODE_FONTDICT
+ : CFF_CODE_TOPDICT,
+ font );
if ( error )
goto Fail_CID;
}
- /* now load the FD Select array */
- error = CFF_Load_FD_Select( &font->fd_select,
- font->charstrings_index.count,
- stream,
- base_offset + dict->cid_fd_select_offset );
+ /* now load the FD Select array; */
+ /* CFF2 omits FDSelect if there is only one FD */
+ if ( !cff2 || fd_index.count > 1 )
+ error = CFF_Load_FD_Select( &font->fd_select,
+ font->charstrings_index.count,
+ stream,
+ base_offset + dict->cid_fd_select_offset );
Fail_CID:
cff_index_done( &fd_index );
@@ -1614,13 +2376,13 @@
font->num_glyphs = font->charstrings_index.count;
error = cff_index_get_pointers( &font->global_subrs_index,
- &font->global_subrs, NULL );
+ &font->global_subrs, NULL, NULL );
if ( error )
goto Exit;
/* 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 );
@@ -1668,7 +2430,7 @@
cff_index_done( &font->charstrings_index );
/* 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 )
{
for ( idx = 0; idx < font->num_subfonts; idx++ )
@@ -1680,6 +2442,7 @@
cff_encoding_done( &font->encoding );
cff_charset_done( &font->charset, font->stream );
+ cff_vstore_done( &font->vstore, memory );
cff_subfont_done( memory, &font->top_font );
diff --git a/third_party/freetype/src/cff/cffload.h b/third_party/freetype/src/cff/cffload.h
index 459e7b0446..8be645261b 100644
--- a/third_party/freetype/src/cff/cffload.h
+++ b/third_party/freetype/src/cff/cffload.h
@@ -4,7 +4,7 @@
/* */
/* OpenType & CFF data/program tables loader (specification). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,12 +16,14 @@
/***************************************************************************/
-#ifndef __CFFLOAD_H__
-#define __CFFLOAD_H__
+#ifndef CFFLOAD_H_
+#define CFFLOAD_H_
#include <ft2build.h>
#include "cfftypes.h"
+#include "cffparse.h"
+#include "cffobjs.h" /* for CFF_Face */
FT_BEGIN_HEADER
@@ -60,24 +62,62 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
- cff_font_load( FT_Library library,
- FT_Stream stream,
- FT_Int face_index,
- CFF_Font font,
- FT_Bool pure_cff );
+ cff_font_load( FT_Library library,
+ FT_Stream stream,
+ FT_Int face_index,
+ CFF_Font font,
+ FT_Bool pure_cff,
+ FT_Bool cff2 );
FT_LOCAL( void )
cff_font_done( CFF_Font font );
+ FT_LOCAL( FT_Error )
+ cff_load_private_dict( CFF_Font font,
+ CFF_SubFont subfont,
+ FT_UInt lenNDV,
+ FT_Fixed* NDV );
+
FT_LOCAL( FT_Byte )
cff_fd_select_get( CFF_FDSelect fdselect,
FT_UInt glyph_index );
+ FT_LOCAL( FT_Bool )
+ cff_blend_check_vector( CFF_Blend blend,
+ FT_UInt vsindex,
+ FT_UInt lenNDV,
+ FT_Fixed* NDV );
+
+ FT_LOCAL( FT_Error )
+ cff_blend_build_vector( CFF_Blend blend,
+ FT_UInt vsindex,
+ FT_UInt lenNDV,
+ FT_Fixed* NDV );
+
+ FT_LOCAL( void )
+ cff_blend_clear( CFF_SubFont subFont );
+
+ FT_LOCAL( FT_Error )
+ cff_blend_doBlend( CFF_SubFont subfont,
+ CFF_Parser parser,
+ FT_UInt numBlends );
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ FT_LOCAL( FT_Error )
+ cff_get_var_blend( CFF_Face face,
+ FT_UInt *num_coords,
+ FT_Fixed* *coords,
+ FT_MM_Var* *mm_var );
+
+ FT_LOCAL( void )
+ cff_done_blend( CFF_Face face );
+#endif
+
FT_END_HEADER
-#endif /* __CFFLOAD_H__ */
+#endif /* CFFLOAD_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cffobjs.c b/third_party/freetype/src/cff/cffobjs.c
index 0e0d5b034b..a63935002c 100644
--- a/third_party/freetype/src/cff/cffobjs.c
+++ b/third_party/freetype/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
/* */
/* OpenType objects manager (body). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -114,7 +114,7 @@
FT_UInt n, count;
- FT_MEM_ZERO( priv, sizeof ( *priv ) );
+ FT_ZERO( priv );
count = priv->num_blue_values = cpriv->num_blue_values;
for ( n = 0; n < count; n++ )
@@ -450,7 +450,7 @@
FT_Int idx;
- for ( idx = 1; idx <= style_name_length; ++idx )
+ for ( idx = 1; idx <= style_name_length; idx++ )
{
if ( family_name[family_name_length - idx] !=
style_name[style_name_length - idx] )
@@ -469,7 +469,7 @@
family_name[idx] == ' ' ||
family_name[idx] == '_' ||
family_name[idx] == '+' ) )
- --idx;
+ idx--;
if ( idx > 0 )
family_name[idx + 1] = '\0';
@@ -491,6 +491,7 @@
FT_Service_PsCMaps psnames;
PSHinter_Service pshinter;
FT_Bool pure_cff = 1;
+ FT_Bool cff2 = 0;
FT_Bool sfnt_format = 0;
FT_Library library = cffface->driver->root.library;
@@ -516,6 +517,7 @@
goto Exit;
/* check whether we have a valid OpenType file */
+ FT_TRACE2(( " " ));
error = sfnt->init_face( stream, face, face_index, num_params, params );
if ( !error )
{
@@ -553,8 +555,18 @@
goto Exit;
}
- /* now load the CFF part of the file */
- error = face->goto_table( face, TTAG_CFF, stream, 0 );
+ /* now load the CFF part of the file; */
+ /* 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 )
goto Exit;
}
@@ -579,14 +591,22 @@
goto Exit;
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 )
goto Exit;
/* if we are performing a simple font format check, exit immediately */
/* (this is here for pure CFF) */
if ( face_index < 0 )
+ {
+ cffface->num_faces = (FT_Long)cff->num_faces;
return FT_Err_Ok;
+ }
cff->pshinter = pshinter;
cff->psnames = psnames;
@@ -622,22 +642,112 @@
FT_TRACE4(( "SIDs\n" ));
/* dump string index, including default strings for convenience */
- for ( idx = 0; idx < cff->num_strings + 390; idx++ )
+ for ( idx = 0; idx <= 390; idx++ )
{
s = cff_index_get_sid_string( cff, idx );
if ( s )
- FT_TRACE4((" %5d %s\n", idx, s ));
+ FT_TRACE4(( " %5d %s\n", idx, s ));
+ }
+
+ /* In Multiple Master CFFs, two SIDs hold the Normalize Design */
+ /* Vector (NDV) and Convert Design Vector (CDV) charstrings, */
+ /* which may contain NULL bytes in the middle of the data, too. */
+ /* We thus access `cff->strings' directly. */
+ for ( idx = 1; idx < cff->num_strings; idx++ )
+ {
+ FT_Byte* s1 = cff->strings[idx - 1];
+ FT_Byte* s2 = cff->strings[idx];
+ FT_PtrDist s1len = s2 - s1 - 1; /* without the final NULL byte */
+ FT_PtrDist l;
+
+
+ FT_TRACE4(( " %5d ", idx + 390 ));
+ for ( l = 0; l < s1len; l++ )
+ FT_TRACE4(( "%c", s1[l] ));
+ FT_TRACE4(( "\n" ));
+ }
+
+ /* print last element */
+ if ( cff->num_strings )
+ {
+ FT_Byte* s1 = cff->strings[cff->num_strings - 1];
+ FT_Byte* s2 = cff->string_pool + cff->string_pool_size;
+ FT_PtrDist s1len = s2 - s1 - 1;
+ FT_PtrDist l;
+
+
+ FT_TRACE4(( " %5d ", cff->num_strings + 390 ));
+ for ( l = 0; l < s1len; l++ )
+ FT_TRACE4(( "%c", s1[l] ));
+ FT_TRACE4(( "\n" ));
}
}
#endif /* FT_DEBUG_LEVEL_TRACE */
+
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+ {
+ FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
+
+ FT_Int instance_index = face_index >> 16;
+
+
+ if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
+ mm &&
+ instance_index > 0 )
+ {
+ FT_MM_Var* mm_var;
+
+
+ error = mm->get_mm_var( cffface, NULL );
+ if ( error )
+ goto Exit;
+
+ mm->get_var_blend( cffface, NULL, NULL, &mm_var );
+
+ if ( mm_var->namedstyle )
+ {
+ FT_Var_Named_Style* named_style;
+ FT_String* style_name;
+
+
+ /* in `face_index', the instance index starts with value 1 */
+ named_style = mm_var->namedstyle + instance_index - 1;
+ error = sfnt->get_name( face,
+ (FT_UShort)named_style->strid,
+ &style_name );
+ if ( error )
+ goto Exit;
+
+ /* set style name; if already set, replace it */
+ if ( face->root.style_name )
+ FT_FREE( face->root.style_name );
+ face->root.style_name = style_name;
+
+ /* finally, select the named instance */
+ error = mm->set_var_design( cffface,
+ mm_var->num_axis,
+ named_style->coords );
+ if ( error )
+ goto Exit;
+ }
+ }
+ }
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+
+
if ( !dict->has_font_matrix )
dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
- /* Normalize the font matrix so that `matrix->yy' is 1; the */
- /* scaling is done with `units_per_em' then (at this point, */
- /* it already contains the scaling factor, but without */
- /* normalization of the matrix). */
+ /* Normalize the font matrix so that `matrix->yy' is 1; if */
+ /* it is zero, we use `matrix->yx' instead. The scaling is */
+ /* done with `units_per_em' then (at this point, it already */
+ /* contains the scaling factor, but without normalization */
+ /* of the matrix). */
/* */
/* Note that the offsets must be expressed in integer font */
/* units. */
@@ -646,9 +756,12 @@
FT_Matrix* matrix = &dict->font_matrix;
FT_Vector* offset = &dict->font_offset;
FT_ULong* upm = &dict->units_per_em;
- FT_Fixed temp = FT_ABS( matrix->yy );
+ FT_Fixed temp;
+ temp = matrix->yy ? FT_ABS( matrix->yy )
+ : FT_ABS( matrix->yx );
+
if ( temp != 0x10000L )
{
*upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
@@ -716,7 +829,10 @@
matrix = &sub->font_matrix;
offset = &sub->font_offset;
upm = &sub->units_per_em;
- temp = FT_ABS( matrix->yy );
+
+ temp = matrix->yy ? FT_ABS( matrix->yy )
+ : FT_ABS( matrix->yx );
+
if ( temp != 0x10000L )
{
@@ -968,7 +1084,7 @@
error = FT_Err_Ok;
/* if no Unicode charmap was previously selected, select this one */
- if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps )
+ if ( !cffface->charmap && nn != (FT_UInt)cffface->num_charmaps )
cffface->charmap = cffface->charmaps[nn];
Skip_Unicode:
@@ -1036,6 +1152,11 @@
FT_FREE( face->extra.data );
}
}
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ cff_done_blend( face );
+ face->blend = NULL;
+#endif
}
@@ -1052,7 +1173,7 @@
driver->hinting_engine = FT_CFF_HINTING_ADOBE;
#endif
- driver->no_stem_darkening = FALSE;
+ driver->no_stem_darkening = TRUE;
driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
diff --git a/third_party/freetype/src/cff/cffobjs.h b/third_party/freetype/src/cff/cffobjs.h
index 3cc953143b..5d26977dc5 100644
--- a/third_party/freetype/src/cff/cffobjs.h
+++ b/third_party/freetype/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
/* */
/* OpenType objects manager (specification). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,8 +16,8 @@
/***************************************************************************/
-#ifndef __CFFOBJS_H__
-#define __CFFOBJS_H__
+#ifndef CFFOBJS_H_
+#define CFFOBJS_H_
#include <ft2build.h>
@@ -179,7 +179,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CFFOBJS_H__ */
+#endif /* CFFOBJS_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cffparse.c b/third_party/freetype/src/cff/cffparse.c
index 063b3517c5..819332b3e8 100644
--- a/third_party/freetype/src/cff/cffparse.c
+++ b/third_party/freetype/src/cff/cffparse.c
@@ -4,7 +4,7 @@
/* */
/* CFF token stream parser (body) */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -23,6 +23,8 @@
#include "cfferrs.h"
#include "cffpic.h"
+#include "cffgload.h"
+#include "cffload.h"
/*************************************************************************/
@@ -35,18 +37,52 @@
#define FT_COMPONENT trace_cffparse
- FT_LOCAL_DEF( void )
+ FT_LOCAL_DEF( FT_Error )
cff_parser_init( CFF_Parser parser,
FT_UInt code,
void* object,
- FT_Library library)
+ FT_Library library,
+ FT_UInt stackSize,
+ FT_UShort num_designs,
+ FT_UShort num_axes )
{
- FT_MEM_ZERO( parser, sizeof ( *parser ) );
+ FT_Memory memory = library->memory; /* for FT_NEW_ARRAY */
+ FT_Error error; /* for FT_NEW_ARRAY */
+
+
+ FT_ZERO( parser );
+#if 0
parser->top = parser->stack;
+#endif
parser->object_code = code;
parser->object = object;
parser->library = library;
+ parser->num_designs = num_designs;
+ parser->num_axes = num_axes;
+
+ /* allocate the stack buffer */
+ if ( FT_NEW_ARRAY( parser->stack, stackSize ) )
+ {
+ FT_FREE( parser->stack );
+ goto Exit;
+ }
+
+ parser->stackSize = stackSize;
+ parser->top = parser->stack; /* empty stack */
+
+ Exit:
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ cff_parser_done( CFF_Parser parser )
+ {
+ FT_Memory memory = parser->library->memory; /* for FT_FREE */
+
+
+ FT_FREE( parser->stack );
}
@@ -397,24 +433,54 @@
/* read a number, either integer or real */
- static FT_Long
- cff_parse_num( FT_Byte** d )
+ FT_LOCAL_DEF( FT_Long )
+ cff_parse_num( CFF_Parser parser,
+ FT_Byte** d )
{
- return **d == 30 ? ( cff_parse_real( d[0], d[1], 0, NULL ) >> 16 )
- : cff_parse_integer( d[0], d[1] );
+ if ( **d == 30 )
+ {
+ /* binary-coded decimal is truncated to integer */
+ return cff_parse_real( *d, parser->limit, 0, NULL ) >> 16;
+ }
+
+ else if ( **d == 255 )
+ {
+ /* 16.16 fixed point is used internally for CFF2 blend results. */
+ /* Since these are trusted values, a limit check is not needed. */
+
+ /* After the 255, 4 bytes give the number. */
+ /* The blend value is converted to integer, with rounding; */
+ /* due to the right-shift we don't need the lowest byte. */
+#if 0
+ return (FT_Short)(
+ ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
+ ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
+ ( (FT_UInt32)*( d[0] + 3 ) << 8 ) |
+ (FT_UInt32)*( d[0] + 4 ) ) + 0x8000U ) >> 16 );
+#else
+ return (FT_Short)(
+ ( ( ( (FT_UInt32)*( d[0] + 1 ) << 16 ) |
+ ( (FT_UInt32)*( d[0] + 2 ) << 8 ) |
+ (FT_UInt32)*( d[0] + 3 ) ) + 0x80U ) >> 8 );
+#endif
+ }
+
+ else
+ return cff_parse_integer( *d, parser->limit );
}
/* read a floating point number, either integer or real */
static FT_Fixed
- do_fixed( FT_Byte** d,
- FT_Long scaling )
+ do_fixed( CFF_Parser parser,
+ FT_Byte** d,
+ FT_Long scaling )
{
if ( **d == 30 )
- return cff_parse_real( d[0], d[1], scaling, NULL );
+ return cff_parse_real( *d, parser->limit, scaling, NULL );
else
{
- FT_Long val = cff_parse_integer( d[0], d[1] );
+ FT_Long val = cff_parse_integer( *d, parser->limit );
if ( scaling )
@@ -442,19 +508,21 @@
/* read a floating point number, either integer or real */
static FT_Fixed
- cff_parse_fixed( FT_Byte** d )
+ cff_parse_fixed( CFF_Parser parser,
+ FT_Byte** d )
{
- return do_fixed( d, 0 );
+ return do_fixed( parser, d, 0 );
}
/* read a floating point number, either integer or real, */
/* but return `10^scaling' times the number read in */
static FT_Fixed
- cff_parse_fixed_scaled( FT_Byte** d,
- FT_Long scaling )
+ cff_parse_fixed_scaled( CFF_Parser parser,
+ FT_Byte** d,
+ FT_Long scaling )
{
- return do_fixed( d, scaling );
+ return do_fixed( parser, d, scaling );
}
@@ -462,13 +530,14 @@
/* and return it as precise as possible -- `scaling' returns */
/* the scaling factor (as a power of 10) */
static FT_Fixed
- cff_parse_fixed_dynamic( FT_Byte** d,
- FT_Long* scaling )
+ cff_parse_fixed_dynamic( CFF_Parser parser,
+ FT_Byte** d,
+ FT_Long* scaling )
{
FT_ASSERT( scaling );
if ( **d == 30 )
- return cff_parse_real( d[0], d[1], 0, scaling );
+ return cff_parse_real( *d, parser->limit, 0, scaling );
else
{
FT_Long number;
@@ -516,7 +585,11 @@
if ( parser->top >= parser->stack + 6 )
{
- FT_Long scaling;
+ FT_Fixed values[6];
+ FT_Long scalings[6];
+
+ FT_Long min_scaling, max_scaling;
+ int i;
error = FT_Err_Ok;
@@ -525,22 +598,36 @@
/* We expect a well-formed font matrix, this is, the matrix elements */
/* `xx' and `yy' are of approximately the same magnitude. To avoid */
- /* loss of precision, we use the magnitude of element `xx' to scale */
- /* all other elements. The scaling factor is then contained in the */
- /* `units_per_em' value. */
+ /* loss of precision, we use the magnitude of the largest matrix */
+ /* element to scale all other elements. The scaling factor is then */
+ /* contained in the `units_per_em' value. */
- matrix->xx = cff_parse_fixed_dynamic( data++, &scaling );
+ max_scaling = FT_LONG_MIN;
+ min_scaling = FT_LONG_MAX;
- scaling = -scaling;
+ for ( i = 0; i < 6; i++ )
+ {
+ values[i] = cff_parse_fixed_dynamic( parser, data++, &scalings[i] );
+ if ( values[i] )
+ {
+ if ( scalings[i] > max_scaling )
+ max_scaling = scalings[i];
+ if ( scalings[i] < min_scaling )
+ min_scaling = scalings[i];
+ }
+ }
- if ( scaling < 0 || scaling > 9 )
+ if ( max_scaling < -9 ||
+ max_scaling > 0 ||
+ ( max_scaling - min_scaling ) < 0 ||
+ ( max_scaling - min_scaling ) > 9 )
{
/* Return default matrix in case of unlikely values. */
FT_TRACE1(( "cff_parse_font_matrix:"
- " strange scaling value for xx element (%d),\n"
+ " strange scaling values (minimum %d, maximum %d),\n"
" "
- " using default matrix\n", scaling ));
+ " using default matrix\n", min_scaling, max_scaling ));
matrix->xx = 0x10000L;
matrix->yx = 0;
@@ -553,13 +640,42 @@
goto Exit;
}
- matrix->yx = cff_parse_fixed_scaled( data++, scaling );
- matrix->xy = cff_parse_fixed_scaled( data++, scaling );
- matrix->yy = cff_parse_fixed_scaled( data++, scaling );
- offset->x = cff_parse_fixed_scaled( data++, scaling );
- offset->y = cff_parse_fixed_scaled( data, scaling );
+ for ( i = 0; i < 6; i++ )
+ {
+ FT_Fixed value = values[i];
+ FT_Long divisor, half_divisor;
+
+
+ if ( !value )
+ continue;
- *upm = (FT_ULong)power_tens[scaling];
+ divisor = power_tens[max_scaling - scalings[i]];
+ half_divisor = divisor >> 1;
+
+ if ( value < 0 )
+ {
+ if ( FT_LONG_MIN + half_divisor < value )
+ values[i] = ( value - half_divisor ) / divisor;
+ else
+ values[i] = FT_LONG_MIN / divisor;
+ }
+ else
+ {
+ if ( FT_LONG_MAX - half_divisor > value )
+ values[i] = ( value + half_divisor ) / divisor;
+ else
+ values[i] = FT_LONG_MAX / divisor;
+ }
+ }
+
+ matrix->xx = values[0];
+ matrix->yx = values[1];
+ matrix->xy = values[2];
+ matrix->yy = values[3];
+ offset->x = values[4];
+ offset->y = values[5];
+
+ *upm = (FT_ULong)power_tens[-max_scaling];
FT_TRACE4(( " [%f %f %f %f %f %f]\n",
(double)matrix->xx / *upm / 65536,
@@ -588,10 +704,10 @@
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 ) );
+ bbox->xMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
+ bbox->yMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
+ bbox->xMax = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
+ bbox->yMax = FT_RoundFix( cff_parse_fixed( parser, data ) );
error = FT_Err_Ok;
FT_TRACE4(( " [%d %d %d %d]\n",
@@ -620,7 +736,7 @@
FT_Long tmp;
- tmp = cff_parse_num( data++ );
+ tmp = cff_parse_num( parser, data++ );
if ( tmp < 0 )
{
FT_ERROR(( "cff_parse_private_dict: Invalid dictionary size\n" ));
@@ -629,7 +745,7 @@
}
dict->private_size = (FT_ULong)tmp;
- tmp = cff_parse_num( data );
+ tmp = cff_parse_num( parser, data );
if ( tmp < 0 )
{
FT_ERROR(( "cff_parse_private_dict: Invalid dictionary offset\n" ));
@@ -649,6 +765,56 @@
}
+ /* The `MultipleMaster' operator comes before any */
+ /* top DICT operators that contain T2 charstrings. */
+
+ static FT_Error
+ cff_parse_multiple_master( CFF_Parser parser )
+ {
+ CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
+ FT_Error error;
+
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ /* beautify tracing message */
+ if ( ft_trace_levels[FT_COMPONENT] < 4 )
+ FT_TRACE1(( "Multiple Master CFFs not supported yet,"
+ " handling first master design only\n" ));
+ else
+ FT_TRACE1(( " (not supported yet,"
+ " handling first master design only)\n" ));
+#endif
+
+ error = FT_ERR( Stack_Underflow );
+
+ /* currently, we handle only the first argument */
+ if ( parser->top >= parser->stack + 5 )
+ {
+ FT_Long num_designs = cff_parse_num( parser, parser->stack );
+
+
+ if ( num_designs > 16 || num_designs < 2 )
+ {
+ FT_ERROR(( "cff_parse_multiple_master:"
+ " Invalid number of designs\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ }
+ else
+ {
+ dict->num_designs = (FT_UShort)num_designs;
+ dict->num_axes = (FT_UShort)( parser->top - parser->stack - 4 );
+
+ parser->num_designs = dict->num_designs;
+ parser->num_axes = dict->num_axes;
+
+ error = FT_Err_Ok;
+ }
+ }
+
+ return error;
+ }
+
+
static FT_Error
cff_parse_cid_ros( CFF_Parser parser )
{
@@ -661,11 +827,11 @@
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_registry = (FT_UInt)cff_parse_num( parser, data++ );
+ dict->cid_ordering = (FT_UInt)cff_parse_num( parser, data++ );
if ( **data == 30 )
FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
- dict->cid_supplement = cff_parse_num( data );
+ dict->cid_supplement = cff_parse_num( parser, data );
if ( dict->cid_supplement < 0 )
FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
dict->cid_supplement ));
@@ -681,6 +847,125 @@
}
+ static FT_Error
+ cff_parse_vsindex( CFF_Parser parser )
+ {
+ /* vsindex operator can only be used in a Private DICT */
+ CFF_Private priv = (CFF_Private)parser->object;
+ FT_Byte** data = parser->stack;
+ CFF_Blend blend;
+ FT_Error error;
+
+
+ if ( !priv || !priv->subfont )
+ {
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ blend = &priv->subfont->blend;
+
+ if ( blend->usedBV )
+ {
+ FT_ERROR(( " cff_parse_vsindex: vsindex not allowed after blend\n" ));
+ error = FT_THROW( Syntax_Error );
+ goto Exit;
+ }
+
+ priv->vsindex = (FT_UInt)cff_parse_num( parser, data++ );
+
+ FT_TRACE4(( " %d\n", priv->vsindex ));
+
+ error = FT_Err_Ok;
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ cff_parse_blend( CFF_Parser parser )
+ {
+ /* blend operator can only be used in a Private DICT */
+ CFF_Private priv = (CFF_Private)parser->object;
+ CFF_SubFont subFont;
+ CFF_Blend blend;
+ FT_UInt numBlends;
+ FT_Error error;
+
+
+ error = FT_ERR( Stack_Underflow );
+
+ if ( !priv || !priv->subfont )
+ {
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ subFont = priv->subfont;
+ blend = &subFont->blend;
+
+ if ( cff_blend_check_vector( blend,
+ priv->vsindex,
+ subFont->lenNDV,
+ subFont->NDV ) )
+ {
+ error = cff_blend_build_vector( blend,
+ priv->vsindex,
+ subFont->lenNDV,
+ subFont->NDV );
+ if ( error )
+ goto Exit;
+ }
+
+ numBlends = (FT_UInt)cff_parse_num( parser, parser->top - 1 );
+ if ( numBlends > parser->stackSize )
+ {
+ FT_ERROR(( "cff_parse_blend: Invalid number of blends\n" ));
+ error = FT_THROW( Invalid_File_Format );
+ goto Exit;
+ }
+
+ FT_TRACE4(( " %d values blended\n", numBlends ));
+
+ error = cff_blend_doBlend( subFont, parser, numBlends );
+
+ blend->usedBV = TRUE;
+
+ Exit:
+ return error;
+ }
+
+
+ /* 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 ) \
CFF_FIELD( code, name, id, cff_kind_num )
#define CFF_FIELD_FIXED( code, name, id ) \
@@ -692,9 +977,6 @@
#define CFF_FIELD_BOOL( code, name, id ) \
CFF_FIELD( code, name, id, cff_kind_bool )
-#define CFFCODE_TOPDICT 0x1000
-#define CFFCODE_PRIVATE 0x2000
-
#ifndef FT_CONFIG_OPTION_PIC
@@ -715,6 +997,15 @@
0, 0 \
},
+#define CFF_FIELD_BLEND( code, id ) \
+ { \
+ cff_kind_blend, \
+ code | CFFCODE, \
+ 0, 0, \
+ cff_parse_blend, \
+ 0, 0 \
+ },
+
#define CFF_FIELD( code, name, id, kind ) \
{ \
kind, \
@@ -758,6 +1049,16 @@
id \
},
+#define CFF_FIELD_BLEND( code, id ) \
+ { \
+ cff_kind_blend, \
+ code | CFFCODE, \
+ 0, 0, \
+ cff_parse_blend, \
+ 0, 0, \
+ id \
+ },
+
#define CFF_FIELD( code, name, id, kind ) \
{ \
kind, \
@@ -965,14 +1266,16 @@
{
FT_UInt v = *p;
-
- if ( v >= 27 && v != 31 )
+ /* Opcode 31 is legacy MM T2 operator, not a number. */
+ /* Opcode 255 is reserved and should not appear in fonts; */
+ /* it is used internally for CFF2 blends. */
+ if ( v >= 27 && v != 31 && v != 255 )
{
/* it's a number; we will push its position on the stack */
- if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
+ if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
goto Stack_Overflow;
- *parser->top ++ = p;
+ *parser->top++ = p;
/* now, skip it */
if ( v == 30 )
@@ -1001,19 +1304,153 @@
else if ( v > 246 )
p += 1;
}
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+ else if ( v == 31 )
+ {
+ /* a Type 2 charstring */
+
+ CFF_Decoder decoder;
+ CFF_FontRec cff_rec;
+ FT_Byte* charstring_base;
+ FT_ULong charstring_len;
+
+ FT_Fixed* stack;
+ FT_Byte* q;
+
+
+ charstring_base = ++p;
+
+ /* search `endchar' operator */
+ for (;;)
+ {
+ if ( p >= limit )
+ goto Exit;
+ if ( *p == 14 )
+ break;
+ p++;
+ }
+
+ charstring_len = (FT_ULong)( p - charstring_base ) + 1;
+
+ /* construct CFF_Decoder object */
+ FT_ZERO( &decoder );
+ FT_ZERO( &cff_rec );
+
+ cff_rec.top_font.font_dict.num_designs = parser->num_designs;
+ cff_rec.top_font.font_dict.num_axes = parser->num_axes;
+ decoder.cff = &cff_rec;
+
+ error = cff_decoder_parse_charstrings( &decoder,
+ charstring_base,
+ charstring_len,
+ 1 );
+
+ /* Now copy the stack data in the temporary decoder object, */
+ /* converting it back to charstring number representations */
+ /* (this is ugly, I know). */
+ /* */
+ /* We overwrite the original top DICT charstring under the */
+ /* assumption that the charstring representation of the result */
+ /* of `cff_decoder_parse_charstrings' is shorter, which should */
+ /* be always true. */
+
+ q = charstring_base - 1;
+ stack = decoder.stack;
+
+ while ( stack < decoder.top )
+ {
+ FT_ULong num;
+ FT_Bool neg;
+
+
+ if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
+ goto Stack_Overflow;
+
+ *parser->top++ = q;
+
+ if ( *stack < 0 )
+ {
+ num = (FT_ULong)-*stack;
+ neg = 1;
+ }
+ else
+ {
+ num = (FT_ULong)*stack;
+ neg = 0;
+ }
+
+ if ( num & 0xFFFFU )
+ {
+ if ( neg )
+ num = (FT_ULong)-num;
+
+ *q++ = 255;
+ *q++ = ( num & 0xFF000000U ) >> 24;
+ *q++ = ( num & 0x00FF0000U ) >> 16;
+ *q++ = ( num & 0x0000FF00U ) >> 8;
+ *q++ = num & 0x000000FFU;
+ }
+ else
+ {
+ num >>= 16;
+
+ if ( neg )
+ {
+ if ( num <= 107 )
+ *q++ = (FT_Byte)( 139 - num );
+ else if ( num <= 1131 )
+ {
+ *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 251 );
+ *q++ = (FT_Byte)( ( num - 108 ) & 0xFF );
+ }
+ else
+ {
+ num = (FT_ULong)-num;
+
+ *q++ = 28;
+ *q++ = (FT_Byte)( num >> 8 );
+ *q++ = (FT_Byte)( num & 0xFF );
+ }
+ }
+ else
+ {
+ if ( num <= 107 )
+ *q++ = (FT_Byte)( num + 139 );
+ else if ( num <= 1131 )
+ {
+ *q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 );
+ *q++ = (FT_Byte)( ( num - 108 ) & 0xFF );
+ }
+ else
+ {
+ *q++ = 28;
+ *q++ = (FT_Byte)( num >> 8 );
+ *q++ = (FT_Byte)( num & 0xFF );
+ }
+ }
+ }
+
+ stack++;
+ }
+ }
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
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 );
+ FT_UInt num_args;
const CFF_Field_Handler* field;
+ if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
+ goto Stack_Overflow;
+
+ num_args = (FT_UInt)( parser->top - parser->stack );
*parser->top = p;
- code = v;
+ code = v;
+
if ( v == 12 )
{
/* two byte operator */
@@ -1048,15 +1485,15 @@
case cff_kind_bool:
case cff_kind_string:
case cff_kind_num:
- val = cff_parse_num( parser->stack );
+ val = cff_parse_num( parser, parser->stack );
goto Store_Number;
case cff_kind_fixed:
- val = cff_parse_fixed( parser->stack );
+ val = cff_parse_fixed( parser, parser->stack );
goto Store_Number;
case cff_kind_fixed_thousand:
- val = cff_parse_fixed_scaled( parser->stack, 3 );
+ val = cff_parse_fixed_scaled( parser, parser->stack, 3 );
Store_Number:
switch ( field->size )
@@ -1125,7 +1562,7 @@
val = 0;
while ( num_args > 0 )
{
- val += cff_parse_num( data++ );
+ val += cff_parse_num( parser, data++ );
switch ( field->size )
{
case (8 / FT_CHAR_BIT):
@@ -1154,7 +1591,7 @@
}
break;
- default: /* callback */
+ default: /* callback or blend */
error = field->reader( parser );
if ( error )
goto Exit;
@@ -1168,7 +1605,10 @@
Found:
/* clear stack */
- parser->top = parser->stack;
+ /* TODO: could clear blend stack here, */
+ /* but we don't have access to subFont */
+ if ( field->kind != cff_kind_blend )
+ parser->top = parser->stack;
}
p++;
}
diff --git a/third_party/freetype/src/cff/cffparse.h b/third_party/freetype/src/cff/cffparse.h
index 8ad02ea1e2..9976d42b18 100644
--- a/third_party/freetype/src/cff/cffparse.h
+++ b/third_party/freetype/src/cff/cffparse.h
@@ -4,7 +4,7 @@
/* */
/* CFF token stream parser (specification) */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,8 +16,8 @@
/***************************************************************************/
-#ifndef __CFF_PARSE_H__
-#define __CFF_PARSE_H__
+#ifndef CFFPARSE_H_
+#define CFFPARSE_H_
#include <ft2build.h>
@@ -28,33 +28,54 @@
FT_BEGIN_HEADER
+ /* CFF uses constant parser stack size; */
+ /* CFF2 can increase from default 193 */
#define CFF_MAX_STACK_DEPTH 96
+#define CFF2_MAX_STACK 513
+#define CFF2_DEFAULT_STACK 193
-#define CFF_CODE_TOPDICT 0x1000
-#define CFF_CODE_PRIVATE 0x2000
+#define CFF_CODE_TOPDICT 0x1000
+#define CFF_CODE_PRIVATE 0x2000
+#define CFF2_CODE_TOPDICT 0x3000
+#define CFF2_CODE_FONTDICT 0x4000
+#define CFF2_CODE_PRIVATE 0x5000
typedef struct CFF_ParserRec_
{
- FT_Library library;
- FT_Byte* start;
- FT_Byte* limit;
- FT_Byte* cursor;
+ FT_Library library;
+ FT_Byte* start;
+ FT_Byte* limit;
+ FT_Byte* cursor;
- FT_Byte* stack[CFF_MAX_STACK_DEPTH + 1];
- FT_Byte** top;
+ FT_Byte** stack;
+ FT_Byte** top;
+ FT_UInt stackSize; /* allocated size */
- FT_UInt object_code;
- void* object;
+ FT_UInt object_code;
+ void* object;
+
+ FT_UShort num_designs; /* a copy of `CFF_FontRecDict->num_designs' */
+ FT_UShort num_axes; /* a copy of `CFF_FontRecDict->num_axes' */
} CFF_ParserRec, *CFF_Parser;
- FT_LOCAL( void )
+ FT_LOCAL( FT_Long )
+ cff_parse_num( CFF_Parser parser,
+ FT_Byte** d );
+
+ FT_LOCAL( FT_Error )
cff_parser_init( CFF_Parser parser,
FT_UInt code,
void* object,
- FT_Library library);
+ FT_Library library,
+ FT_UInt stackSize,
+ FT_UShort num_designs,
+ FT_UShort num_axes );
+
+ FT_LOCAL( void )
+ cff_parser_done( CFF_Parser parser );
FT_LOCAL( FT_Error )
cff_parser_run( CFF_Parser parser,
@@ -72,6 +93,7 @@ FT_BEGIN_HEADER
cff_kind_bool,
cff_kind_delta,
cff_kind_callback,
+ cff_kind_blend,
cff_kind_max /* do not remove */
};
@@ -100,7 +122,7 @@ FT_BEGIN_HEADER
FT_END_HEADER
-#endif /* __CFF_PARSE_H__ */
+#endif /* CFFPARSE_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cffpic.c b/third_party/freetype/src/cff/cffpic.c
index d40dec50e9..4e9ba12b3f 100644
--- a/third_party/freetype/src/cff/cffpic.c
+++ b/third_party/freetype/src/cff/cffpic.c
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for cff module. */
/* */
-/* Copyright 2009-2015 by */
+/* Copyright 2009-2017 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
diff --git a/third_party/freetype/src/cff/cffpic.h b/third_party/freetype/src/cff/cffpic.h
index 9a221a7b7e..0b89fcb5e5 100644
--- a/third_party/freetype/src/cff/cffpic.h
+++ b/third_party/freetype/src/cff/cffpic.h
@@ -4,7 +4,7 @@
/* */
/* The FreeType position independent code services for cff module. */
/* */
-/* Copyright 2009-2015 by */
+/* Copyright 2009-2017 by */
/* Oran Agra and Mickey Gabel. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -16,8 +16,8 @@
/***************************************************************************/
-#ifndef __CFFPIC_H__
-#define __CFFPIC_H__
+#ifndef CFFPIC_H_
+#define CFFPIC_H_
#include FT_INTERNAL_PIC_H
@@ -32,6 +32,7 @@
#define CFF_SERVICE_CID_INFO_GET cff_service_cid_info
#define CFF_SERVICE_PROPERTIES_GET cff_service_properties
#define CFF_SERVICES_GET cff_services
+#define CFF_SERVICE_MULTI_MASTERS_GET cff_service_multi_masters
#define CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec
#define CFF_CMAP_UNICODE_CLASS_REC_GET cff_cmap_unicode_class_rec
#define CFF_FIELD_HANDLERS_GET cff_field_handlers
@@ -102,7 +103,7 @@ FT_END_HEADER
/* */
-#endif /* __CFFPIC_H__ */
+#endif /* CFFPIC_H_ */
/* END */
diff --git a/third_party/freetype/src/cff/cfftoken.h b/third_party/freetype/src/cff/cfftoken.h
index 5b32076ab8..3222e933f1 100644
--- a/third_party/freetype/src/cff/cfftoken.h
+++ b/third_party/freetype/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
/* */
/* CFF token definitions (specification only). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -20,7 +20,7 @@
#define FT_STRUCTURE CFF_FontRecDictRec
#undef CFFCODE
-#define CFFCODE CFFCODE_TOPDICT
+#define CFFCODE CFF_CODE_TOPDICT
CFF_FIELD_STRING ( 0, version, "Version" )
CFF_FIELD_STRING ( 1, notice, "Notice" )
@@ -38,6 +38,9 @@
CFF_FIELD_NUM ( 13, unique_id, "UniqueID" )
CFF_FIELD_CALLBACK( 5, font_bbox, "FontBBox" )
CFF_FIELD_NUM ( 0x108, stroke_width, "StrokeWidth" )
+#if 0
+ CFF_FIELD_DELTA ( 14, xuid, 16, "XUID" )
+#endif
CFF_FIELD_NUM ( 15, charset_offset, "charset" )
CFF_FIELD_NUM ( 16, encoding_offset, "Encoding" )
CFF_FIELD_NUM ( 17, charstrings_offset, "CharStrings" )
@@ -48,8 +51,13 @@
#if 0
CFF_FIELD_STRING ( 0x116, base_font_name, "BaseFontName" )
CFF_FIELD_DELTA ( 0x117, base_font_blend, 16, "BaseFontBlend" )
+#endif
+
+ /* the next two operators were removed from the Type2 specification */
+ /* in version 16-March-2000 */
CFF_FIELD_CALLBACK( 0x118, multiple_master, "MultipleMaster" )
- CFF_FIELD_CALLBACK( 0x119, blend_axis_types, "BlendAxisTypes" )
+#if 0
+ CFF_FIELD_CALLBACK( 0x11A, blend_axis_types, "BlendAxisTypes" )
#endif
CFF_FIELD_CALLBACK( 0x11E, cid_ros, "ROS" )
@@ -70,7 +78,7 @@
#undef FT_STRUCTURE
#define FT_STRUCTURE CFF_PrivateRec
#undef CFFCODE
-#define CFFCODE CFFCODE_PRIVATE
+#define CFFCODE CFF_CODE_PRIVATE
CFF_FIELD_DELTA ( 6, blue_values, 14, "BlueValues" )
CFF_FIELD_DELTA ( 7, other_blues, 10, "OtherBlues" )
@@ -94,4 +102,49 @@
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_NUM ( 24, vstore_offset, "vstore" )
+ 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_CALLBACK ( 22, vsindex, "vsindex" )
+ CFF_FIELD_BLEND ( 23, "blend" )
+ CFF_FIELD_NUM ( 19, local_subrs_offset, "Subrs" )
+
+
/* END */
diff --git a/third_party/freetype/src/cff/cfftypes.h b/third_party/freetype/src/cff/cfftypes.h
index de8a5ee9b4..412712c86c 100644
--- a/third_party/freetype/src/cff/cfftypes.h
+++ b/third_party/freetype/src/cff/cfftypes.h
@@ -5,7 +5,7 @@
/* Basic OpenType/CFF type definitions and interface (specification */
/* only). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2017 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -17,8 +17,8 @@
/***************************************************************************/
-#ifndef __CFFTYPES_H__
-#define __CFFTYPES_H__
+#ifndef CFFTYPES_H_
+#define CFFTYPES_H_
#include <ft2build.h>
@@ -64,6 +64,7 @@ FT_BEGIN_HEADER
{
FT_Stream stream;
FT_ULong start;
+ FT_UInt hdr_size;
FT_UInt count;
FT_Byte off_size;
FT_ULong data_offset;
@@ -102,6 +103,79 @@ FT_BEGIN_HEADER
} CFF_CharsetRec, *CFF_Charset;
+ /* cf. similar fields in file `ttgxvar.h' from the `truetype' module */
+
+ typedef struct CFF_VarData_
+ {
+#if 0
+ FT_UInt itemCount; /* not used; always zero */
+ FT_UInt shortDeltaCount; /* not used; always zero */
+#endif
+
+ FT_UInt regionIdxCount; /* number of regions in this var data */
+ FT_UInt* regionIndices; /* array of `regionCount' indices; */
+ /* these index `varRegionList' */
+ } CFF_VarData;
+
+
+ /* contribution of one axis to a region */
+ typedef struct CFF_AxisCoords_
+ {
+ FT_Fixed startCoord;
+ FT_Fixed peakCoord; /* zero peak means no effect (factor = 1) */
+ FT_Fixed endCoord;
+
+ } CFF_AxisCoords;
+
+
+ typedef struct CFF_VarRegion_
+ {
+ CFF_AxisCoords* axisList; /* array of axisCount records */
+
+ } CFF_VarRegion;
+
+
+ typedef struct CFF_VStoreRec_
+ {
+ FT_UInt dataCount;
+ CFF_VarData* varData; /* array of dataCount records */
+ /* vsindex indexes this array */
+ FT_UShort axisCount;
+ FT_UInt regionCount; /* total number of regions defined */
+ CFF_VarRegion* varRegionList;
+
+ } CFF_VStoreRec, *CFF_VStore;
+
+
+ /* forward reference */
+ typedef struct CFF_FontRec_* CFF_Font;
+
+
+ /* This object manages one cached blend vector. */
+ /* */
+ /* There is a BlendRec for Private DICT parsing in each subfont */
+ /* and a BlendRec for charstrings in CF2_Font instance data. */
+ /* A cached BV may be used across DICTs or Charstrings if inputs */
+ /* have not changed. */
+ /* */
+ /* `usedBV' is reset at the start of each parse or charstring. */
+ /* vsindex cannot be changed after a BV is used. */
+ /* */
+ /* Note: NDV is long (32/64 bit), while BV is 16.16 (FT_Int32). */
+ typedef struct CFF_BlendRec_
+ {
+ FT_Bool builtBV; /* blendV has been built */
+ FT_Bool usedBV; /* blendV has been used */
+ CFF_Font font; /* top level font struct */
+ FT_UInt lastVsindex; /* last vsindex used */
+ FT_UInt lenNDV; /* normDV length (aka numAxes) */
+ FT_Fixed* lastNDV; /* last NDV used */
+ FT_UInt lenBV; /* BlendV length (aka numMasters) */
+ FT_Int32* BV; /* current blendV (per DICT/glyph) */
+
+ } CFF_BlendRec, *CFF_Blend;
+
+
typedef struct CFF_FontRecDictRec_
{
FT_UInt version;
@@ -145,9 +219,23 @@ FT_BEGIN_HEADER
FT_ULong cid_fd_select_offset;
FT_UInt cid_font_name;
+ /* the next fields come from the data of the deprecated */
+ /* `MultipleMaster' operator; they are needed to parse the (also */
+ /* deprecated) `blend' operator in Type 2 charstrings */
+ FT_UShort num_designs;
+ FT_UShort num_axes;
+
+ /* fields for CFF2 */
+ FT_ULong vstore_offset;
+ FT_UInt maxstack;
+
} CFF_FontRecDictRec, *CFF_FontRecDict;
+ /* forward reference */
+ typedef struct CFF_SubFontRec_* CFF_SubFont;
+
+
typedef struct CFF_PrivateRec_
{
FT_Byte num_blue_values;
@@ -180,6 +268,10 @@ FT_BEGIN_HEADER
FT_Pos default_width;
FT_Pos nominal_width;
+ /* fields for CFF2 */
+ FT_UInt vsindex;
+ CFF_SubFont subfont;
+
} CFF_PrivateRec, *CFF_Private;
@@ -207,10 +299,29 @@ FT_BEGIN_HEADER
CFF_FontRecDictRec font_dict;
CFF_PrivateRec private_dict;
- CFF_IndexRec local_subrs_index;
- FT_Byte** local_subrs; /* array of pointers into Local Subrs INDEX data */
+ /* fields for CFF2 */
+ CFF_BlendRec blend; /* current blend vector */
+ FT_UInt lenNDV; /* current length NDV or zero */
+ FT_Fixed* NDV; /* ptr to current NDV or NULL */
+
+ /* `blend_stack' is a writable buffer to hold blend results. */
+ /* This buffer is to the side of the normal cff parser stack; */
+ /* `cff_parse_blend' and `cff_blend_doBlend' push blend results here. */
+ /* The normal stack then points to these values instead of the DICT */
+ /* because all other operators in Private DICT clear the stack. */
+ /* `blend_stack' could be cleared at each operator other than blend. */
+ /* Blended values are stored as 5-byte fixed point values. */
+
+ FT_Byte* blend_stack; /* base of stack allocation */
+ FT_Byte* blend_top; /* first empty slot */
+ FT_UInt blend_used; /* number of bytes in use */
+ FT_UInt blend_alloc; /* number of bytes allocated */
- } CFF_SubFontRec, *CFF_SubFont;
+ CFF_IndexRec local_subrs_index;
+ FT_Byte** local_subrs; /* array of pointers */
+ /* into Local Subrs INDEX data */
+
+ } CFF_SubFontRec;
#define CFF_MAX_CID_FONTS 256
@@ -218,16 +329,20 @@ FT_BEGIN_HEADER
typedef struct CFF_FontRec_
{
+ FT_Library library;
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_UInt num_faces;
FT_UInt num_glyphs;
FT_Byte version_major;
FT_Byte version_minor;
FT_Byte header_size;
- FT_Byte absolute_offsize;
+ FT_UInt top_dict_length; /* cff2 only */
+
+ FT_Bool cff2;
CFF_IndexRec name_index;
CFF_IndexRec top_dict_index;
@@ -250,6 +365,7 @@ FT_BEGIN_HEADER
FT_UInt num_strings;
FT_Byte** strings;
FT_Byte* string_pool;
+ FT_ULong string_pool_size;
CFF_SubFontRec top_font;
FT_UInt num_subfonts;
@@ -273,12 +389,14 @@ FT_BEGIN_HEADER
/* since version 2.4.12 */
FT_Generic cf2_instance;
- } CFF_FontRec, *CFF_Font;
+ CFF_VStoreRec vstore; /* parsed vstore structure */
+
+ } CFF_FontRec;
FT_END_HEADER
-#endif /* __CFFTYPES_H__ */
+#endif /* CFFTYPES_H_ */
/* END */