diff options
| author | Po Lu | 2023-12-09 11:49:04 +0800 |
|---|---|---|
| committer | Po Lu | 2023-12-09 11:49:04 +0800 |
| commit | 414301bce19e24889ce970d60f798e178e556818 (patch) | |
| tree | 8d8201348329c793de0079a37d50704f7e4fb447 | |
| parent | ef732bd2083c5f28c37dc52a6f96923eed2f5aa8 (diff) | |
| download | emacs-414301bce19e24889ce970d60f798e178e556818.tar.gz emacs-414301bce19e24889ce970d60f798e178e556818.zip | |
Correct phantom point generation and MDAP
* src/sfnt.c (sfnt_interpret_mdrp): Cease applying cvt
cut in, as this is contrary to the specification.
(sfnt_interpret_simple_glyph): Correct typo.
(main): Revise tests.
| -rw-r--r-- | src/sfnt.c | 67 |
1 files changed, 32 insertions, 35 deletions
diff --git a/src/sfnt.c b/src/sfnt.c index 34239973797..bc2ffdea9dc 100644 --- a/src/sfnt.c +++ b/src/sfnt.c | |||
| @@ -10381,8 +10381,8 @@ sfnt_interpret_mdrp (struct sfnt_interpreter *interpreter, | |||
| 10381 | uint32_t opcode) | 10381 | uint32_t opcode) |
| 10382 | { | 10382 | { |
| 10383 | uint32_t p; | 10383 | uint32_t p; |
| 10384 | sfnt_f26dot6 distance, delta; | 10384 | sfnt_f26dot6 distance, applied; |
| 10385 | sfnt_f26dot6 current_projection, original_projection; | 10385 | sfnt_f26dot6 current_projection; |
| 10386 | sfnt_f26dot6 x, y, org_x, org_y; | 10386 | sfnt_f26dot6 x, y, org_x, org_y; |
| 10387 | sfnt_f26dot6 rx, ry, org_rx, org_ry; | 10387 | sfnt_f26dot6 rx, ry, org_rx, org_ry; |
| 10388 | 10388 | ||
| @@ -10394,20 +10394,21 @@ sfnt_interpret_mdrp (struct sfnt_interpreter *interpreter, | |||
| 10394 | sfnt_address_zp0 (interpreter, interpreter->state.rp0, | 10394 | sfnt_address_zp0 (interpreter, interpreter->state.rp0, |
| 10395 | &rx, &ry, &org_rx, &org_ry); | 10395 | &rx, &ry, &org_rx, &org_ry); |
| 10396 | 10396 | ||
| 10397 | /* Calculate the distance between P and rp0 prior to hinting. */ | ||
| 10397 | distance = DUAL_PROJECT (org_x - org_rx, | 10398 | distance = DUAL_PROJECT (org_x - org_rx, |
| 10398 | org_y - org_ry); | 10399 | org_y - org_ry); |
| 10399 | original_projection = distance; | 10400 | |
| 10401 | /* Calculate the distance between P and rp0 as of now in the hinting | ||
| 10402 | process. */ | ||
| 10400 | current_projection = PROJECT (x - rx, y - ry); | 10403 | current_projection = PROJECT (x - rx, y - ry); |
| 10401 | 10404 | ||
| 10402 | /* Test against the single width value. */ | 10405 | /* Test against the single width value. */ |
| 10403 | 10406 | ||
| 10404 | delta = sfnt_sub (distance, | 10407 | if (interpreter->state.sw_cut_in > 0 |
| 10405 | interpreter->state.single_width_value); | 10408 | && distance < (interpreter->state.single_width_value |
| 10406 | 10409 | + interpreter->state.sw_cut_in) | |
| 10407 | if (delta < 0) | 10410 | && distance > (interpreter->state.single_width_value |
| 10408 | delta = -delta; | 10411 | - interpreter->state.sw_cut_in)) |
| 10409 | |||
| 10410 | if (delta < interpreter->state.sw_cut_in) | ||
| 10411 | { | 10412 | { |
| 10412 | /* Use the single width instead, as the CVT entry is too | 10413 | /* Use the single width instead, as the CVT entry is too |
| 10413 | small. */ | 10414 | small. */ |
| @@ -10418,38 +10419,34 @@ sfnt_interpret_mdrp (struct sfnt_interpreter *interpreter, | |||
| 10418 | distance = -interpreter->state.single_width_value; | 10419 | distance = -interpreter->state.single_width_value; |
| 10419 | } | 10420 | } |
| 10420 | 10421 | ||
| 10421 | /* Flag B means look at the cvt cut in and round the | 10422 | /* Flag B implies that the distance should be rounded. The CVT cut |
| 10422 | distance. */ | 10423 | in is not taken into account by MDRP, contrary to earlier |
| 10424 | presumptions. */ | ||
| 10423 | 10425 | ||
| 10424 | if (opcode & 4) | 10426 | if (opcode & 4) |
| 10425 | { | 10427 | applied = sfnt_round_symmetric (interpreter, distance); |
| 10426 | delta = sfnt_sub (distance, original_projection); | 10428 | else |
| 10427 | 10429 | applied = distance; | |
| 10428 | if (delta < 0) | ||
| 10429 | delta = -delta; | ||
| 10430 | |||
| 10431 | if (delta > interpreter->state.cvt_cut_in) | ||
| 10432 | distance = original_projection; | ||
| 10433 | |||
| 10434 | /* Now, round the distance. */ | ||
| 10435 | distance = sfnt_round_symmetric (interpreter, distance); | ||
| 10436 | } | ||
| 10437 | 10430 | ||
| 10438 | /* Flag C means look at the minimum distance. */ | 10431 | /* Flag C means look at the minimum distance. */ |
| 10439 | 10432 | ||
| 10440 | if (opcode & 8) | 10433 | if (opcode & 8) |
| 10441 | { | 10434 | { |
| 10442 | if (original_projection >= 0 | 10435 | /* Test the sign of the initial distance, but compare the |
| 10443 | && distance < interpreter->state.minimum_distance) | 10436 | distance that will be applied in reality against the minimum |
| 10444 | distance = interpreter->state.minimum_distance; | 10437 | distance. */ |
| 10445 | else if (original_projection < 0 | 10438 | |
| 10446 | && distance > -interpreter->state.minimum_distance) | 10439 | if (distance >= 0 |
| 10447 | distance = -interpreter->state.minimum_distance; | 10440 | && applied < interpreter->state.minimum_distance) |
| 10441 | applied = interpreter->state.minimum_distance; | ||
| 10442 | else if (distance < 0 | ||
| 10443 | && applied > -interpreter->state.minimum_distance) | ||
| 10444 | applied = -interpreter->state.minimum_distance; | ||
| 10448 | } | 10445 | } |
| 10449 | 10446 | ||
| 10450 | /* Finally, move the point. */ | 10447 | /* Finally, move the point. */ |
| 10451 | sfnt_move_zp1 (interpreter, p, 1, | 10448 | sfnt_move_zp1 (interpreter, p, 1, |
| 10452 | sfnt_sub (distance, current_projection)); | 10449 | sfnt_sub (applied, current_projection)); |
| 10453 | 10450 | ||
| 10454 | /* Set RP1 to RP0 and RP2 to the point. If flag 3 is set, also make | 10451 | /* Set RP1 to RP0 and RP2 to the point. If flag 3 is set, also make |
| 10455 | it RP0. */ | 10452 | it RP0. */ |
| @@ -11431,8 +11428,8 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph, | |||
| 11431 | /* Load phantom points. */ | 11428 | /* Load phantom points. */ |
| 11432 | zone->y_points[i] = phantom_point_1_y; | 11429 | zone->y_points[i] = phantom_point_1_y; |
| 11433 | zone->y_points[i + 1] = phantom_point_2_y; | 11430 | zone->y_points[i + 1] = phantom_point_2_y; |
| 11434 | zone->y_current[i] = phantom_point_1_x; | 11431 | zone->y_current[i] = phantom_point_1_y; |
| 11435 | zone->y_current[i + 1] = phantom_point_2_x; | 11432 | zone->y_current[i + 1] = phantom_point_2_y; |
| 11436 | 11433 | ||
| 11437 | /* Load phantom point flags. */ | 11434 | /* Load phantom point flags. */ |
| 11438 | zone->flags[i] = SFNT_POINT_PHANTOM; | 11435 | zone->flags[i] = SFNT_POINT_PHANTOM; |
| @@ -19549,8 +19546,8 @@ main (int argc, char **argv) | |||
| 19549 | return 1; | 19546 | return 1; |
| 19550 | } | 19547 | } |
| 19551 | 19548 | ||
| 19552 | #define FANCY_PPEM 18 | 19549 | #define FANCY_PPEM 40 |
| 19553 | #define EASY_PPEM 18 | 19550 | #define EASY_PPEM 40 |
| 19554 | 19551 | ||
| 19555 | interpreter = NULL; | 19552 | interpreter = NULL; |
| 19556 | head = sfnt_read_head_table (fd, font); | 19553 | head = sfnt_read_head_table (fd, font); |