diff --git a/ChangeLog b/ChangeLog index cb2b7768a..95873ed75 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2017-02-20 Werner Lemberg + + [cff] Finish support for `random' operator. + + * src/cff/cfftypes.h (CFF_SubFontRec): Add `random' field. + + * src/cff/cffobjs.c: Updated. + (cff_driver_init): Initialize random seed value. + + * src/cff/cffload.c (cff_random): New function. + (cff_subfont_load): Add `face' argument. + Update all callers. + Initialize random number generator with a proper seed value. + (cff_font_load): Add `face' argument. + Update all callers. + + * src/cff/cffload.h: Updated. + + * src/cff/cf2intrp.c (CF2_FIXME): Removed. + (cf2_interpT2CharString) : Implement opcode. + + * src/cff/cffgload.c (cff_decoder_parse_charstrings): Don't + initialize random seed value. + : Use new random seed framework. + 2017-02-20 Werner Lemberg [cff] Sanitize `initialRandomSeed'. diff --git a/src/cff/cf2intrp.c b/src/cff/cf2intrp.c index 6bf298a4d..62c696d08 100644 --- a/src/cff/cf2intrp.c +++ b/src/cff/cf2intrp.c @@ -60,12 +60,6 @@ #define FT_COMPONENT trace_cf2interp - /* some operators are not implemented yet */ -#define CF2_FIXME FT_TRACE4(( "cf2_interpT2CharString:" \ - " operator not implemented yet\n" )) - - - FT_LOCAL_DEF( void ) cf2_hintmask_init( CF2_HintMask hintmask, FT_Error* error ) @@ -1268,10 +1262,23 @@ continue; /* do not clear the stack */ case cf2_escRANDOM: /* in spec */ - FT_TRACE4(( " random\n" )); + { + CF2_F16Dot16 r; - CF2_FIXME; - break; + + FT_TRACE4(( " random\n" )); + + /* only use the lower 16 bits of `random' */ + /* to generate a number in the range (0;1] */ + r = (CF2_F16Dot16) + ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); + + decoder->current_subfont->random = + cff_random( decoder->current_subfont->random ); + + cf2_stack_pushFixed( opStack, r ); + } + continue; /* do not clear the stack */ case cf2_escMUL: { diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index f8e80c100..4803b4bbc 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -457,7 +457,7 @@ decoder->glyph_width = sub->private_dict.default_width; decoder->nominal_width = sub->private_dict.nominal_width; - decoder->current_subfont = sub; /* for Adobe's CFF handler */ + decoder->current_subfont = sub; Exit: return error; @@ -913,7 +913,6 @@ FT_Byte* limit; CFF_Builder* builder = &decoder->builder; FT_Pos x, y; - FT_Fixed seed; FT_Fixed* stack; FT_Int charstring_type = decoder->cff->top_font.font_dict.charstring_type; @@ -929,15 +928,6 @@ decoder->num_hints = 0; decoder->read_width = 1; - /* compute random seed from stack address of parameter */ - seed = (FT_Fixed)( ( (FT_Offset)(char*)&seed ^ - (FT_Offset)(char*)&decoder ^ - (FT_Offset)(char*)&charstring_base ) & - FT_ULONG_MAX ); - seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; - if ( seed == 0 ) - seed = 0x7384; - /* initialize the decoder */ decoder->top = decoder->stack; decoder->zone = decoder->zones; @@ -2104,22 +2094,16 @@ break; case cff_op_random: - { - FT_Fixed Rand; + FT_TRACE4(( " random\n" )); + /* only use the lower 16 bits of `random' */ + /* to generate a number in the range (0;1] */ + args[0] = (FT_Fixed) + ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); + args++; - FT_TRACE4(( " rand\n" )); - - Rand = seed; - if ( Rand >= 0x8000L ) - Rand++; - - args[0] = Rand; - seed = FT_MulFix( seed, 0x10000L - seed ); - if ( seed == 0 ) - seed += 0x2873; - args++; - } + decoder->current_subfont->random = + cff_random( decoder->current_subfont->random ); break; case cff_op_mul: diff --git a/src/cff/cffload.c b/src/cff/cffload.c index 9122ff9ab..47626a714 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1931,6 +1931,18 @@ } + FT_LOCAL_DEF( FT_UInt32 ) + cff_random( FT_UInt32 r ) + { + /* a 32bit version of the `xorshift' algorithm */ + r ^= r << 13; + r ^= r >> 17; + r ^= r << 5; + + return r; + } + + /* 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 */ @@ -1944,7 +1956,8 @@ FT_Stream stream, FT_ULong base_offset, FT_UInt code, - CFF_Font font ) + CFF_Font font, + CFF_Face face ) { FT_Error error; CFF_ParserRec parser; @@ -2041,6 +2054,54 @@ if ( error ) goto Exit; + if ( !cff2 ) + { + /* + * Initialize the random number generator. + * + * . If we have a face-specific seed, use it. + * If non-zero, update it to a positive value. + * + * . Otherwise, use the seed from the CFF driver. + * If non-zero, update it to a positive value. + * + * . If the random value is zero, use the seed given by the subfont's + * `initialRandomSeed' value. + * + */ + if ( face->root.internal->random_seed == -1 ) + { + CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face ); + + + subfont->random = (FT_UInt32)driver->random_seed; + if ( driver->random_seed ) + { + do + { + driver->random_seed = (FT_Int32)cff_random( driver->random_seed ); + + } while ( driver->random_seed < 0 ); + } + } + else + { + subfont->random = (FT_UInt32)face->root.internal->random_seed; + if ( face->root.internal->random_seed ) + { + do + { + face->root.internal->random_seed = + (FT_Int32)cff_random( face->root.internal->random_seed ); + + } while ( face->root.internal->random_seed < 0 ); + } + } + + if ( !subfont->random ) + subfont->random = (FT_UInt32)priv->initial_random_seed; + } + /* read the local subrs, if any */ if ( priv->local_subrs_offset ) { @@ -2086,6 +2147,7 @@ FT_Stream stream, FT_Int face_index, CFF_Font font, + CFF_Face face, FT_Bool pure_cff, FT_Bool cff2 ) { @@ -2283,7 +2345,8 @@ stream, base_offset, cff2 ? CFF2_CODE_TOPDICT : CFF_CODE_TOPDICT, - font ); + font, + face ); if ( error ) goto Exit; @@ -2350,7 +2413,8 @@ base_offset, cff2 ? CFF2_CODE_FONTDICT : CFF_CODE_TOPDICT, - font ); + font, + face ); if ( error ) goto Fail_CID; } diff --git a/src/cff/cffload.h b/src/cff/cffload.h index 8be645261..1709a661e 100644 --- a/src/cff/cffload.h +++ b/src/cff/cffload.h @@ -61,11 +61,15 @@ FT_BEGIN_HEADER FT_UInt cid ); + FT_LOCAL( FT_UInt32 ) + cff_random( FT_UInt32 r ); + FT_LOCAL( FT_Error ) cff_font_load( FT_Library library, FT_Stream stream, FT_Int face_index, CFF_Font font, + CFF_Face face, FT_Bool pure_cff, FT_Bool cff2 ); diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c index f0320afa4..67bf0cc41 100644 --- a/src/cff/cffobjs.c +++ b/src/cff/cffobjs.c @@ -595,6 +595,7 @@ stream, face_index, cff, + face, pure_cff, cff2 ); if ( error ) @@ -1157,6 +1158,8 @@ { CFF_Driver driver = (CFF_Driver)module; + FT_UInt32 seed; + /* set default property values, cf. `ftcffdrv.h' */ #ifdef CFF_CONFIG_OPTION_OLD_ENGINE @@ -1176,6 +1179,18 @@ driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; + /* compute random seed from some memory addresses */ + seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ + (FT_Offset)(char*)&module ^ + (FT_Offset)(char*)module->memory ); + seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); + + driver->random_seed = (FT_Int32)seed; + if ( driver->random_seed < 0 ) + driver->random_seed = -driver->random_seed; + else if ( driver->random_seed == 0 ) + driver->random_seed = 123456789; + return FT_Err_Ok; } diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h index 0c24ed500..8d43e2834 100644 --- a/src/cff/cfftypes.h +++ b/src/cff/cfftypes.h @@ -321,6 +321,8 @@ FT_BEGIN_HEADER FT_Byte** local_subrs; /* array of pointers */ /* into Local Subrs INDEX data */ + FT_UInt32 random; + } CFF_SubFontRec;