[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) <cf2_escRANDOM>: Implement opcode.

* src/cff/cffgload.c (cff_decoder_parse_charstrings): Don't
initialize random seed value.
<cff_op_random>: Use new random seed framework.
This commit is contained in:
Werner Lemberg 2017-02-20 09:15:13 +01:00
parent 156b30b1aa
commit e706798d43
7 changed files with 138 additions and 37 deletions

View File

@ -1,3 +1,28 @@
2017-02-20 Werner Lemberg <wl@gnu.org>
[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) <cf2_escRANDOM>: Implement opcode.
* src/cff/cffgload.c (cff_decoder_parse_charstrings): Don't
initialize random seed value.
<cff_op_random>: Use new random seed framework.
2017-02-20 Werner Lemberg <wl@gnu.org>
[cff] Sanitize `initialRandomSeed'.

View File

@ -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:
{

View File

@ -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:

View File

@ -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;
}

View File

@ -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 );

View File

@ -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;
}

View File

@ -321,6 +321,8 @@ FT_BEGIN_HEADER
FT_Byte** local_subrs; /* array of pointers */
/* into Local Subrs INDEX data */
FT_UInt32 random;
} CFF_SubFontRec;