diff options
| author | Po Lu | 2024-01-22 15:29:18 +0800 |
|---|---|---|
| committer | Po Lu | 2024-01-22 16:02:05 +0800 |
| commit | 05495bfa6c39816e210bf655c0cbd44ba6dfcc7c (patch) | |
| tree | c63538976c84bdce7867970132730daa81c3ecf2 /src | |
| parent | 088afa7e2f08f4eb4e39aae5db4faa33857bf544 (diff) | |
| download | emacs-05495bfa6c39816e210bf655c0cbd44ba6dfcc7c.tar.gz emacs-05495bfa6c39816e210bf655c0cbd44ba6dfcc7c.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/sfnt.c | 82 |
1 files 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) | |||
| 6490 | #endif | 6490 | #endif |
| 6491 | } | 6491 | } |
| 6492 | 6492 | ||
| 6493 | /* Multiply the specified 2.14 number with another signed 32 bit | 6493 | /* Multiply the specified two 26.6 fixed point numbers A and B, with |
| 6494 | number. Return the result as a signed 32 bit number. */ | 6494 | rounding. Return the result, or an undefined value upon |
| 6495 | overflow. */ | ||
| 6495 | 6496 | ||
| 6496 | static int32_t | 6497 | static sfnt_f26dot6 |
| 6497 | sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) | 6498 | sfnt_mul_f26dot6_round (sfnt_f26dot6 a, sfnt_f26dot6 b) |
| 6498 | { | 6499 | { |
| 6499 | #ifdef INT64_MAX | 6500 | #ifdef INT64_MAX |
| 6500 | int64_t product; | 6501 | int64_t product; |
| 6501 | 6502 | ||
| 6502 | product = (int64_t) a * (int64_t) b; | 6503 | product = (int64_t) a * (int64_t) b; |
| 6503 | 6504 | ||
| 6504 | return product / (int64_t) 16384; | 6505 | /* This can be done quickly with int64_t. */ |
| 6505 | #else | 6506 | return (product + 32) / (int64_t) 64; |
| 6507 | #else /* !INT64_MAX */ | ||
| 6506 | int sign; | 6508 | int sign; |
| 6507 | 6509 | ||
| 6508 | sign = 1; | 6510 | sign = 1; |
| @@ -6513,61 +6515,48 @@ sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) | |||
| 6513 | if (b < 0) | 6515 | if (b < 0) |
| 6514 | sign = -sign; | 6516 | sign = -sign; |
| 6515 | 6517 | ||
| 6516 | return sfnt_multiply_divide (abs (a), abs (b), | 6518 | return sfnt_multiply_divide_round (abs (a), abs (b), |
| 6517 | 16384) * sign; | 6519 | 32, 64) * sign; |
| 6518 | #endif | 6520 | #endif /* INT64_MAX */ |
| 6519 | } | 6521 | } |
| 6520 | 6522 | ||
| 6521 | /* Multiply the specified 26.6 fixed point number X by the specified | 6523 | /* Multiply the specified 2.14 number with another signed 32 bit |
| 6522 | 16.16 fixed point number Y with symmetric rounding. | 6524 | number. Return the result as a signed 32 bit number. */ |
| 6523 | |||
| 6524 | The 26.6 fixed point number must fit inside -32768 to 32767.ffff. | ||
| 6525 | Value is otherwise undefined. */ | ||
| 6526 | 6525 | ||
| 6527 | static sfnt_f26dot6 | 6526 | static int32_t |
| 6528 | sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y) | 6527 | sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) |
| 6529 | { | 6528 | { |
| 6530 | #ifdef INT64_MAX | 6529 | #ifdef INT64_MAX |
| 6531 | uint64_t product; | 6530 | int64_t product; |
| 6532 | int sign; | ||
| 6533 | |||
| 6534 | sign = 1; | ||
| 6535 | |||
| 6536 | if (x < 0) | ||
| 6537 | { | ||
| 6538 | x = -x; | ||
| 6539 | sign = -sign; | ||
| 6540 | } | ||
| 6541 | |||
| 6542 | if (y < 0) | ||
| 6543 | { | ||
| 6544 | y = -y; | ||
| 6545 | sign = -sign; | ||
| 6546 | } | ||
| 6547 | 6531 | ||
| 6548 | product = (uint64_t) y * (uint64_t) x; | 6532 | product = (int64_t) a * (int64_t) b; |
| 6549 | 6533 | ||
| 6550 | /* This can be done quickly with int64_t. */ | 6534 | return product / (int64_t) 16384; |
| 6551 | return ((int64_t) (product + 32768) | ||
| 6552 | / (int64_t) 65536) * sign; | ||
| 6553 | #else | 6535 | #else |
| 6554 | struct sfnt_large_integer temp; | ||
| 6555 | int sign; | 6536 | int sign; |
| 6556 | 6537 | ||
| 6557 | sign = 1; | 6538 | sign = 1; |
| 6558 | 6539 | ||
| 6559 | if (x < 0) | 6540 | if (a < 0) |
| 6560 | sign = -sign; | 6541 | sign = -sign; |
| 6561 | 6542 | ||
| 6562 | if (y < 0) | 6543 | if (b < 0) |
| 6563 | sign = -sign; | 6544 | sign = -sign; |
| 6564 | 6545 | ||
| 6565 | sfnt_multiply_divide_1 (abs (x), abs (y), &temp); | 6546 | return sfnt_multiply_divide (abs (a), abs (b), |
| 6566 | sfnt_large_integer_add (&temp, 32768); | 6547 | 16384) * sign; |
| 6567 | return sfnt_multiply_divide_2 (&temp, 65536) * sign; | ||
| 6568 | #endif | 6548 | #endif |
| 6569 | } | 6549 | } |
| 6570 | 6550 | ||
| 6551 | /* Multiply the specified 26.6 fixed point number X by the specified | ||
| 6552 | 16.16 fixed point number Y with rounding. */ | ||
| 6553 | |||
| 6554 | static sfnt_f26dot6 | ||
| 6555 | sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y) | ||
| 6556 | { | ||
| 6557 | return sfnt_mul_fixed (x, y); | ||
| 6558 | } | ||
| 6559 | |||
| 6571 | /* Return the floor of the specified 26.6 fixed point value X. */ | 6560 | /* Return the floor of the specified 26.6 fixed point value X. */ |
| 6572 | 6561 | ||
| 6573 | static sfnt_f26dot6 | 6562 | static sfnt_f26dot6 |
| @@ -7582,12 +7571,13 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 7582 | 7571 | ||
| 7583 | #define MUL() \ | 7572 | #define MUL() \ |
| 7584 | { \ | 7573 | { \ |
| 7585 | sfnt_f26dot6 n2, n1; \ | 7574 | sfnt_f26dot6 n2, n1, r; \ |
| 7586 | \ | 7575 | \ |
| 7587 | n2 = POP (); \ | 7576 | n2 = POP (); \ |
| 7588 | n1 = POP (); \ | 7577 | n1 = POP (); \ |
| 7589 | \ | 7578 | \ |
| 7590 | PUSH_UNCHECKED (sfnt_mul_f26dot6 (n2, n1)); \ | 7579 | r = sfnt_mul_f26dot6_round (n2, n1); \ |
| 7580 | PUSH_UNCHECKED (r); \ | ||
| 7591 | } | 7581 | } |
| 7592 | 7582 | ||
| 7593 | #define ABS() \ | 7583 | #define ABS() \ |
| @@ -12357,10 +12347,10 @@ sfnt_interpret_control_value_program (struct sfnt_interpreter *interpreter, | |||
| 12357 | sfnt_interpret_run (interpreter, | 12347 | sfnt_interpret_run (interpreter, |
| 12358 | SFNT_RUN_CONTEXT_CONTROL_VALUE_PROGRAM); | 12348 | SFNT_RUN_CONTEXT_CONTROL_VALUE_PROGRAM); |
| 12359 | 12349 | ||
| 12360 | /* If instruct_control & 4, then changes to the graphics state made | 12350 | /* If instruct_control & 2, then changes to the graphics state made |
| 12361 | in this program should be reverted. */ | 12351 | in this program should be reverted. */ |
| 12362 | 12352 | ||
| 12363 | if (interpreter->state.instruct_control & 4) | 12353 | if (interpreter->state.instruct_control & 2) |
| 12364 | sfnt_init_graphics_state (&interpreter->state); | 12354 | sfnt_init_graphics_state (&interpreter->state); |
| 12365 | else | 12355 | else |
| 12366 | { | 12356 | { |