From 1bf690dffd3a24455c42113eeb2aff4fa6883ebd Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 22 Jan 2024 15:29:18 +0800 Subject: [PATCH] Correct values of INSTCTRL flags tested * src/sfnt.c (sfnt_mul_f26dot6_round): New function. (sfnt_mul_f26dot6_fixed): Replace by call to sfnt_mul_fixed_round. (MUL): Round result, as the Apple and MS scalers do. (sfnt_interpret_control_value_program): The instruction control flag which reverts CVT modifications is 2, not 4. (cherry picked from commit 05495bfa6c39816e210bf655c0cbd44ba6dfcc7c) --- src/sfnt.c | 82 ++++++++++++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 46 deletions(-) diff --git a/src/sfnt.c b/src/sfnt.c index a70994fbe67..7b4c5544dc1 100644 --- a/src/sfnt.c +++ b/src/sfnt.c @@ -6490,19 +6490,21 @@ sfnt_mul_f26dot6 (sfnt_f26dot6 a, sfnt_f26dot6 b) #endif } -/* Multiply the specified 2.14 number with another signed 32 bit - number. Return the result as a signed 32 bit number. */ +/* Multiply the specified two 26.6 fixed point numbers A and B, with + rounding. Return the result, or an undefined value upon + overflow. */ -static int32_t -sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) +static sfnt_f26dot6 +sfnt_mul_f26dot6_round (sfnt_f26dot6 a, sfnt_f26dot6 b) { #ifdef INT64_MAX int64_t product; product = (int64_t) a * (int64_t) b; - return product / (int64_t) 16384; -#else + /* This can be done quickly with int64_t. */ + return (product + 32) / (int64_t) 64; +#else /* !INT64_MAX */ int sign; sign = 1; @@ -6513,61 +6515,48 @@ sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) if (b < 0) sign = -sign; - return sfnt_multiply_divide (abs (a), abs (b), - 16384) * sign; -#endif + return sfnt_multiply_divide_round (abs (a), abs (b), + 32, 64) * sign; +#endif /* INT64_MAX */ } -/* Multiply the specified 26.6 fixed point number X by the specified - 16.16 fixed point number Y with symmetric rounding. - - The 26.6 fixed point number must fit inside -32768 to 32767.ffff. - Value is otherwise undefined. */ +/* Multiply the specified 2.14 number with another signed 32 bit + number. Return the result as a signed 32 bit number. */ -static sfnt_f26dot6 -sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y) +static int32_t +sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) { #ifdef INT64_MAX - uint64_t product; - int sign; - - sign = 1; - - if (x < 0) - { - x = -x; - sign = -sign; - } - - if (y < 0) - { - y = -y; - sign = -sign; - } + int64_t product; - product = (uint64_t) y * (uint64_t) x; + product = (int64_t) a * (int64_t) b; - /* This can be done quickly with int64_t. */ - return ((int64_t) (product + 32768) - / (int64_t) 65536) * sign; + return product / (int64_t) 16384; #else - struct sfnt_large_integer temp; int sign; sign = 1; - if (x < 0) + if (a < 0) sign = -sign; - if (y < 0) + if (b < 0) sign = -sign; - sfnt_multiply_divide_1 (abs (x), abs (y), &temp); - sfnt_large_integer_add (&temp, 32768); - return sfnt_multiply_divide_2 (&temp, 65536) * sign; + return sfnt_multiply_divide (abs (a), abs (b), + 16384) * sign; #endif } +/* Multiply the specified 26.6 fixed point number X by the specified + 16.16 fixed point number Y with rounding. */ + +static sfnt_f26dot6 +sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y) +{ + return sfnt_mul_fixed (x, y); +} + /* Return the floor of the specified 26.6 fixed point value X. */ static sfnt_f26dot6 @@ -7582,12 +7571,13 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, #define MUL() \ { \ - sfnt_f26dot6 n2, n1; \ + sfnt_f26dot6 n2, n1, r; \ \ n2 = POP (); \ n1 = POP (); \ \ - PUSH_UNCHECKED (sfnt_mul_f26dot6 (n2, n1)); \ + r = sfnt_mul_f26dot6_round (n2, n1); \ + PUSH_UNCHECKED (r); \ } #define ABS() \ @@ -12357,10 +12347,10 @@ sfnt_interpret_control_value_program (struct sfnt_interpreter *interpreter, sfnt_interpret_run (interpreter, SFNT_RUN_CONTEXT_CONTROL_VALUE_PROGRAM); - /* If instruct_control & 4, then changes to the graphics state made + /* If instruct_control & 2, then changes to the graphics state made in this program should be reverted. */ - if (interpreter->state.instruct_control & 4) + if (interpreter->state.instruct_control & 2) sfnt_init_graphics_state (&interpreter->state); else { -- 2.39.5