aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2024-01-17 09:30:47 +0800
committerPo Lu2024-01-17 09:30:47 +0800
commitdaec3e7b410cdb8deefbb241d056f8b42dfb40ac (patch)
tree99f1df71c09e51bf9bec0534cf430d69a64bfb6a
parentf19f5604deb72c4d548702b2d9b8565805ffbca1 (diff)
downloademacs-daec3e7b410cdb8deefbb241d056f8b42dfb40ac.tar.gz
emacs-daec3e7b410cdb8deefbb241d056f8b42dfb40ac.zip
Increase accuracy of IP instruction
* src/sfnt.c (sfnt_interpret_ip): Avoid precision loss by retrieving original positions from the unscaled outline, whenever possible.
-rw-r--r--src/sfnt.c86
1 files changed, 83 insertions, 3 deletions
diff --git a/src/sfnt.c b/src/sfnt.c
index 2f0153b9a75..ca4c60e8e3a 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -9640,6 +9640,8 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
9640 sfnt_f26dot6 new_distance; 9640 sfnt_f26dot6 new_distance;
9641 uint32_t p; 9641 uint32_t p;
9642 sfnt_f26dot6 x, y, original_x, original_y; 9642 sfnt_f26dot6 x, y, original_x, original_y;
9643 struct sfnt_interpreter_zone *zone;
9644 bool scale;
9643 9645
9644 /* First load both reference points. */ 9646 /* First load both reference points. */
9645 sfnt_address_zp0 (interpreter, interpreter->state.rp1, 9647 sfnt_address_zp0 (interpreter, interpreter->state.rp1,
@@ -9649,6 +9651,57 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
9649 &rp2x, &rp2y, &rp2_original_x, 9651 &rp2x, &rp2y, &rp2_original_x,
9650 &rp2_original_y); 9652 &rp2_original_y);
9651 9653
9654 /* If RP1, RP2, and all arguments all fall within the glyph zone and
9655 a simple glyph is loaded, replace their original coordinates as
9656 loaded here with coordinates from the unscaled glyph outline. */
9657
9658 zone = interpreter->glyph_zone;
9659 scale = false;
9660
9661 if (zone && zone->simple
9662 && interpreter->state.zp0
9663 && interpreter->state.zp1
9664 && interpreter->state.zp2)
9665 {
9666 p = interpreter->state.rp1;
9667
9668 /* If P is a phantom point... */
9669 if (p >= zone->simple->number_of_points)
9670 {
9671 /* ...scale the phantom point to the size of the original
9672 outline. */
9673 rp1_original_x = sfnt_div_fixed (rp1_original_x,
9674 interpreter->scale);
9675 rp1_original_y = sfnt_div_fixed (rp1_original_y,
9676 interpreter->scale);
9677 }
9678 else
9679 {
9680 rp1_original_x = zone->simple->x_coordinates[p];
9681 rp1_original_y = zone->simple->y_coordinates[p];
9682 }
9683
9684 p = interpreter->state.rp2;
9685
9686 /* If P is a phantom point... */
9687 if (p >= zone->simple->number_of_points)
9688 {
9689 /* ...scale the phantom point to the size of the original
9690 outline. */
9691 rp2_original_x = sfnt_div_fixed (rp2_original_x,
9692 interpreter->scale);
9693 rp2_original_y = sfnt_div_fixed (rp2_original_y,
9694 interpreter->scale);
9695 }
9696 else
9697 {
9698 rp2_original_x = zone->simple->x_coordinates[p];
9699 rp2_original_y = zone->simple->y_coordinates[p];
9700 }
9701
9702 scale = true;
9703 }
9704
9652 /* Get the original distance between of RP1 and RP2 measured 9705 /* Get the original distance between of RP1 and RP2 measured
9653 relative to the dual projection vector. */ 9706 relative to the dual projection vector. */
9654 range = sfnt_dual_project_vector (interpreter, 9707 range = sfnt_dual_project_vector (interpreter,
@@ -9657,6 +9710,9 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
9657 sfnt_sub (rp2_original_y, 9710 sfnt_sub (rp2_original_y,
9658 rp1_original_y)); 9711 rp1_original_y));
9659 9712
9713 if (scale)
9714 range = sfnt_mul_fixed_round (range, interpreter->scale);
9715
9660 /* Get the new distance. */ 9716 /* Get the new distance. */
9661 new_range = sfnt_dual_project_vector (interpreter, 9717 new_range = sfnt_dual_project_vector (interpreter,
9662 sfnt_sub (rp2x, rp1x), 9718 sfnt_sub (rp2x, rp1x),
@@ -9670,6 +9726,25 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
9670 sfnt_address_zp2 (interpreter, p, &x, &y, &original_x, 9726 sfnt_address_zp2 (interpreter, p, &x, &y, &original_x,
9671 &original_y); 9727 &original_y);
9672 9728
9729 if (scale)
9730 {
9731 /* If P is a phantom point... */
9732 if (p >= zone->simple->number_of_points)
9733 {
9734 /* ...scale the phantom point to the size of the original
9735 outline. */
9736 original_x = sfnt_div_fixed (original_x,
9737 interpreter->scale);
9738 original_y = sfnt_div_fixed (original_y,
9739 interpreter->scale);
9740 }
9741 else
9742 {
9743 original_x = zone->simple->x_coordinates[p];
9744 original_y = zone->simple->y_coordinates[p];
9745 }
9746 }
9747
9673 /* Now compute the old distance from this point to rp1. */ 9748 /* Now compute the old distance from this point to rp1. */
9674 org_distance 9749 org_distance
9675 = sfnt_dual_project_vector (interpreter, 9750 = sfnt_dual_project_vector (interpreter,
@@ -9678,6 +9753,10 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
9678 sfnt_sub (original_y, 9753 sfnt_sub (original_y,
9679 rp1_original_y)); 9754 rp1_original_y));
9680 9755
9756 if (scale)
9757 org_distance = sfnt_mul_fixed_round (org_distance,
9758 interpreter->scale);
9759
9681 /* And the current distance from this point to rp1, so 9760 /* And the current distance from this point to rp1, so
9682 how much to move can be determined. */ 9761 how much to move can be determined. */
9683 cur_distance 9762 cur_distance
@@ -11447,7 +11526,8 @@ sfnt_interpret_mirp (struct sfnt_interpreter *interpreter,
11447 coordinate from the font designer's intentions, either exaggerating 11526 coordinate from the font designer's intentions, either exaggerating
11448 or neutralizing the slant of the stem to which it belongs. 11527 or neutralizing the slant of the stem to which it belongs.
11449 11528
11450 This behavior applies only to MDRP, which see. */ 11529 This behavior applies only to MDRP (which see), although a similar
11530 strategy is also applied while interpreting IP instructions. */
11451 11531
11452static sfnt_f26dot6 11532static sfnt_f26dot6
11453sfnt_project_zp1_zp0_org (struct sfnt_interpreter *interpreter, 11533sfnt_project_zp1_zp0_org (struct sfnt_interpreter *interpreter,
@@ -20715,8 +20795,8 @@ main (int argc, char **argv)
20715 return 1; 20795 return 1;
20716 } 20796 }
20717 20797
20718#define FANCY_PPEM 16 20798#define FANCY_PPEM 14
20719#define EASY_PPEM 16 20799#define EASY_PPEM 14
20720 20800
20721 interpreter = NULL; 20801 interpreter = NULL;
20722 head = sfnt_read_head_table (fd, font); 20802 head = sfnt_read_head_table (fd, font);