diff --git a/ChangeLog b/ChangeLog index b8847559a..ceb6166b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2016-02-15 Werner Lemberg + + [cff] Partially handle `load' and `store' ops in old CFF engine. + + Now all glyphs of MM CFFs like `ITCGaramondMM-It.otf' can be + displayed. + + * src/cff/cffgload.c (cff_decoder_parse_charstrings) : Partially implement it. + + * src/cff/cffparse.c (cff_parser_init): Add new parameter to pass + the number of Multiple Master axes. + Update all callers. + (cff_parse_multiple_master): Get number of axes. + (cff_parser_run) : Updated. + * src/cff/cffparse.h: Updated. + (CFF_ParserRec): Add `num_axes' field. + + * src/cff/cffload.c: Updated. + + * src/cff/cfftypes.h (CFF_FontRecDictRec): Add `num_axes' field. + 2016-02-15 Werner Lemberg [cff] Correctly trace SIDs that contain NULL bytes. diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index 2a2f60f0d..752c18ed9 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -919,6 +919,8 @@ 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; @@ -2248,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; } @@ -2272,16 +2278,43 @@ case cff_op_store: /* this operator was removed from the Type2 specification */ /* in version 16-March-2000 */ - FT_TRACE4(( " store\n")); - 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: /* this operator was removed from the Type2 specification */ /* in version 16-March-2000 */ - FT_TRACE4(( " load\n" )); + { + FT_Int reg_idx = (FT_Int)args[0]; + FT_Int idx = (FT_Int)args[1]; + FT_Int count = (FT_Int)args[2]; - goto Unimplemented; + + 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; case cff_op_blend: /* this operator was removed from the Type2 specification */ @@ -2577,7 +2610,6 @@ break; default: - Unimplemented: FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); if ( ip[-1] == 12 ) diff --git a/src/cff/cffload.c b/src/cff/cffload.c index 920f10b68..9d3846cb5 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1325,6 +1325,7 @@ CFF_CODE_TOPDICT, &font->font_dict, library, + 0, 0 ); /* set defaults */ @@ -1383,7 +1384,8 @@ CFF_CODE_PRIVATE, priv, library, - top->num_designs ); + top->num_designs, + top->num_axes ); if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) || FT_FRAME_ENTER( font->font_dict.private_size ) ) diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c index 616023a7e..921c1a13c 100644 --- a/src/cff/cffparse.c +++ b/src/cff/cffparse.c @@ -41,7 +41,8 @@ FT_UInt code, void* object, FT_Library library, - FT_UShort num_designs ) + FT_UShort num_designs, + FT_UShort num_axes ) { FT_MEM_ZERO( parser, sizeof ( *parser ) ); @@ -50,6 +51,7 @@ parser->object = object; parser->library = library; parser->num_designs = num_designs; + parser->num_axes = num_axes; } @@ -682,7 +684,11 @@ 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; } } @@ -1075,6 +1081,7 @@ FT_MEM_ZERO( &cff_rec, sizeof ( 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, diff --git a/src/cff/cffparse.h b/src/cff/cffparse.h index 682ada04a..a95970edc 100644 --- a/src/cff/cffparse.h +++ b/src/cff/cffparse.h @@ -36,18 +36,19 @@ FT_BEGIN_HEADER 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[CFF_MAX_STACK_DEPTH + 1]; + FT_Byte** top; - 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_designs; /* a copy of `CFF_FontRecDict->num_designs' */ + FT_UShort num_axes; /* a copy of `CFF_FontRecDict->num_axes' */ } CFF_ParserRec, *CFF_Parser; @@ -57,7 +58,8 @@ FT_BEGIN_HEADER FT_UInt code, void* object, FT_Library library, - FT_UShort num_designs ); + FT_UShort num_designs, + FT_UShort num_axes ); FT_LOCAL( FT_Error ) cff_parser_run( CFF_Parser parser, diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h index b2320fd93..4426c7e4f 100644 --- a/src/cff/cfftypes.h +++ b/src/cff/cfftypes.h @@ -145,10 +145,11 @@ FT_BEGIN_HEADER FT_ULong cid_fd_select_offset; FT_UInt cid_font_name; - /* the next field comes from the data of the deprecated */ - /* `MultipleMaster' operator; it is needed to parse the (also */ - /* deprecated) `blend' operator in Type 2 charstrings */ + /* 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; } CFF_FontRecDictRec, *CFF_FontRecDict;