diff --git a/ChangeLog b/ChangeLog index 8aaa78e58..cfb9ae508 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2016-08-16 Werner Lemberg + + [truetype] Fix `MPS' instruction. + + According to Greg Hitchcock, MPS in DWrite really returns the point + size. + + * src/truetype/ttobjs.h (TT_SizeRec): Add `point_size' member. + + * src/truetype/ttdriver.c (tt_size_request): Set `point_size'. + + * src/truetype/ttinterp.h (TT_ExecContextRec): Add `pointSize' + member. + + * src/truetype/ttinterp.c (TT_Load_Context): Updated. + (Ins_MPS): Fix instruction. + 2016-08-16 Werner Lemberg [lzw] Optimize last commit. diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index 2659b9c9b..6520c93df 100644 --- a/src/truetype/ttdriver.c +++ b/src/truetype/ttdriver.c @@ -339,6 +339,25 @@ { error = tt_size_reset( ttsize ); ttsize->root.metrics = ttsize->metrics; + +#ifdef TT_USE_BYTECODE_INTERPRETER + /* for the `MPS' bytecode instruction we need the point size */ + { + FT_UInt resolution = ttsize->metrics.x_ppem > ttsize->metrics.y_ppem + ? req->horiResolution + : req->vertResolution; + + + /* if we don't have a resolution value, assume 72dpi */ + if ( req->type == FT_SIZE_REQUEST_TYPE_SCALES || + !resolution ) + resolution = 72; + + ttsize->point_size = FT_MulDiv( ttsize->ttmetrics.ppem, + 64 * 72, + resolution ); + } +#endif } return error; diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index f23a3dd41..caeb6ca68 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -397,6 +397,7 @@ exec->maxIDefs = size->max_instruction_defs; exec->FDefs = size->function_defs; exec->IDefs = size->instruction_defs; + exec->pointSize = size->point_size; exec->tt_metrics = size->ttmetrics; exec->metrics = size->metrics; @@ -2580,13 +2581,20 @@ Ins_MPS( TT_ExecContext exc, FT_Long* args ) { - /* Note: The point size should be irrelevant in a given font program; */ - /* we thus decide to return only the PPEM value. */ -#if 0 - args[0] = exc->metrics.pointSize; -#else - args[0] = exc->func_cur_ppem( exc ); -#endif + if ( NO_SUBPIXEL_HINTING ) + { + /* Microsoft's GDI bytecode interpreter always returns value 12; */ + /* we return the current PPEM value instead. */ + args[0] = exc->func_cur_ppem( exc ); + } + else + { + /* A possible practical application of the MPS instruction is to */ + /* implement optical scaling and similar features, which should be */ + /* based on perceptual attributes, thus independent of the */ + /* resolution. */ + args[0] = exc->pointSize; + } } diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h index df7ce51f1..53f09446b 100644 --- a/src/truetype/ttinterp.h +++ b/src/truetype/ttinterp.h @@ -170,6 +170,7 @@ FT_BEGIN_HEADER pts, twilight; + FT_Long pointSize; /* in 26.6 format */ FT_Size_Metrics metrics; TT_Size_Metrics tt_metrics; /* size metrics */ diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h index ed61a7d51..98ad38373 100644 --- a/src/truetype/ttobjs.h +++ b/src/truetype/ttobjs.h @@ -286,6 +286,8 @@ FT_BEGIN_HEADER #ifdef TT_USE_BYTECODE_INTERPRETER + FT_Long point_size; /* for the `MPS' bytecode instruction */ + FT_UInt num_function_defs; /* number of function definitions */ FT_UInt max_function_defs; TT_DefArray function_defs; /* table of function definitions */