aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-02-05 20:49:19 +0800
committerPo Lu2023-02-05 20:49:19 +0800
commit87cdbbeb8a229926277578a9f5f958438e8679b6 (patch)
tree5b0b7ff3d5ab27488553a9527af715687758ea79 /src
parent420533a8f9b345699dad9eeafeb3ccecfed516b2 (diff)
downloademacs-87cdbbeb8a229926277578a9f5f958438e8679b6.tar.gz
emacs-87cdbbeb8a229926277578a9f5f958438e8679b6.zip
Update Android port
* src/sfnt.c (struct sfnt_graphics_state): (LOOPCALL): (DELTAC3): (PROJECT): (SHPIX): (sfnt_save_projection_vector): (sfnt_check_zp0): (sfnt_dual_project_vector): (sfnt_interpret_scfs): (sfnt_round_symmetric): (sfnt_interpret_miap): (sfnt_interpret_alignrp_1): (sfnt_interpret_alignrp): (sfnt_measure_distance): (sfnt_interpret_msirp): (sfnt_interpret_ip): (sfnt_interpret_mdap): (sfnt_deltap): (sfnt_dual_project_onto_any_vector): (sfnt_validate_gs): (sfnt_set_projection_vector): (sfnt_interpret_shp): (sfnt_interpret_run): (sfnt_check_sloop): (main): Check in more WIP font code.
Diffstat (limited to 'src')
-rw-r--r--src/sfnt.c693
1 files changed, 666 insertions, 27 deletions
diff --git a/src/sfnt.c b/src/sfnt.c
index 0d87ed36dad..6d060fde7df 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -1,4 +1,4 @@
1/* sfnt format font support for GNU Emacs. 1/* TrueType format font support for GNU Emacs.
2 2
3Copyright (C) 2023 Free Software Foundation, Inc. 3Copyright (C) 2023 Free Software Foundation, Inc.
4 4
@@ -106,7 +106,21 @@ xfree (void *ptr)
106 106
107 Try not to keep this file too dependent on Emacs. Everything Lisp 107 Try not to keep this file too dependent on Emacs. Everything Lisp
108 related goes in sfntfont.c. The author wants to keep using it for 108 related goes in sfntfont.c. The author wants to keep using it for
109 some other (free) software. */ 109 some other (free) software.
110
111 The source of reference is the TrueType Reference Manual, published
112 by Apple Computer, which is currently found at:
113
114 https://developer.apple.com/fonts/TrueType-Reference-Manual/
115
116 Apple's TrueType implementation is notably missing features
117 provided by Microsoft's extended OpenType scaler, such as the two
118 additional phantom points on the Y axis, and also behaves
119 differently, especially when it comes to considering phantom points
120 as anchors in compound glyphs.
121
122 As a result, do not expect this scaler to work well with Microsoft
123 fonts such as Arial. */
110 124
111 125
112 126
@@ -4915,6 +4929,12 @@ struct sfnt_graphics_state
4915 sfnt_f26dot6 (*project) (sfnt_f26dot6, sfnt_f26dot6, 4929 sfnt_f26dot6 (*project) (sfnt_f26dot6, sfnt_f26dot6,
4916 struct sfnt_interpreter *); 4930 struct sfnt_interpreter *);
4917 4931
4932 /* Pointer to the function used to project euclidean vectors onto
4933 the dual projection vector. Value is the magnitude of the
4934 projected vector. */
4935 sfnt_f26dot6 (*dual_project) (sfnt_f26dot6, sfnt_f26dot6,
4936 struct sfnt_interpreter *);
4937
4918 /* Pointer to the function used to move specified points 4938 /* Pointer to the function used to move specified points
4919 along the freedom vector by a distance specified in terms 4939 along the freedom vector by a distance specified in terms
4920 of the projection vector. */ 4940 of the projection vector. */
@@ -5776,6 +5796,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
5776 \ 5796 \
5777 id = POP (); \ 5797 id = POP (); \
5778 n = POP (); \ 5798 n = POP (); \
5799 def = NULL; /* Pacify -fanalyzer. */ \
5779 \ 5800 \
5780 if (n > 65535) \ 5801 if (n > 65535) \
5781 TRAP ("invalid LOOPCALL count"); \ 5802 TRAP ("invalid LOOPCALL count"); \
@@ -6444,7 +6465,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6444 6465
6445 6466
6446 6467
6447/* CVT delta exception instructions. 6468/* CVT and point delta exception instructions.
6448 6469
6449 ``Exceptions'' can be placed directly inside the control value 6470 ``Exceptions'' can be placed directly inside the control value
6450 table, as it is reloaded every time the point size changes. */ 6471 table, as it is reloaded every time the point size changes. */
@@ -6503,6 +6524,54 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6503 goto deltac3_start; \ 6524 goto deltac3_start; \
6504 } 6525 }
6505 6526
6527#define DELTAP1() \
6528 { \
6529 uint32_t n, argn, pn; \
6530 \
6531 n = POP (); \
6532 \
6533 deltap1_start: \
6534 if (!n) \
6535 break; \
6536 \
6537 argn = POP (); \
6538 pn = POP (); \
6539 sfnt_deltap (1, interpreter, argn, pn); \
6540 goto deltap1_start; \
6541 }
6542
6543#define DELTAP2() \
6544 { \
6545 uint32_t n, argn, pn; \
6546 \
6547 n = POP (); \
6548 \
6549 deltap2_start: \
6550 if (!n) \
6551 break; \
6552 \
6553 argn = POP (); \
6554 pn = POP (); \
6555 sfnt_deltap (2, interpreter, argn, pn); \
6556 goto deltap2_start; \
6557 }
6558
6559#define DELTAP3() \
6560 { \
6561 uint32_t n, argn, pn; \
6562 \
6563 n = POP (); \
6564 \
6565 deltap3_start: \
6566 if (!n) \
6567 break; \
6568 \
6569 argn = POP (); \
6570 pn = POP (); \
6571 sfnt_deltap (3, interpreter, argn, pn); \
6572 goto deltap3_start; \
6573 }
6574
6506 6575
6507 6576
6508/* Anachronistic angle instructions. */ 6577/* Anachronistic angle instructions. */
@@ -6521,6 +6590,12 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6521 6590
6522/* Projection and freedom vector operations. */ 6591/* Projection and freedom vector operations. */
6523 6592
6593#define PROJECT(x, y) \
6594 sfnt_project_vector (interpreter, x, y)
6595
6596#define DUAL_PROJECT(x, y) \
6597 sfnt_dual_project_vector (interpreter, x, y)
6598
6524#define SVTCAy() \ 6599#define SVTCAy() \
6525 { \ 6600 { \
6526 sfnt_set_freedom_vector (interpreter, \ 6601 sfnt_set_freedom_vector (interpreter, \
@@ -6738,6 +6813,85 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6738 interpreter->state.loop = 1; \ 6813 interpreter->state.loop = 1; \
6739 } 6814 }
6740 6815
6816#define IP() \
6817 { \
6818 sfnt_interpret_ip (interpreter); \
6819 }
6820
6821#define MSIRP() \
6822 { \
6823 sfnt_f26dot6 d; \
6824 uint32_t p; \
6825 \
6826 d = POP (); \
6827 p = POP (); \
6828 \
6829 sfnt_interpret_msirp (interpreter, d, p, \
6830 opcode); \
6831 }
6832
6833#define ALIGNRP() \
6834 { \
6835 sfnt_interpret_alignrp (interpreter); \
6836 }
6837
6838#define MIAP() \
6839 { \
6840 uint32_t cvt; \
6841 uint32_t p; \
6842 \
6843 cvt = POP (); \
6844 p = POP (); \
6845 \
6846 sfnt_interpret_miap (interpreter, cvt, p, \
6847 opcode); \
6848 }
6849
6850#define GC() \
6851 { \
6852 uint32_t p; \
6853 sfnt_f26dot6 x, y, value; \
6854 sfnt_f26dot6 org_x, org_y; \
6855 \
6856 p = POP (); \
6857 \
6858 sfnt_address_zp2 (interpreter, p, &x, &y, \
6859 &org_x, &org_y); \
6860 \
6861 if (opcode == 0x47) \
6862 value = DUAL_PROJECT (org_x, org_y); \
6863 else \
6864 value = PROJECT (x, y); \
6865 \
6866 PUSH (value); \
6867 }
6868
6869#define SCFS() \
6870 { \
6871 uint32_t p; \
6872 sfnt_f26dot6 c; \
6873 \
6874 c = POP (); \
6875 p = POP (); \
6876 \
6877 sfnt_interpret_scfs (interpreter, c, p); \
6878 }
6879
6880#define MD() \
6881 { \
6882 uint32_t p1, p2; \
6883 sfnt_f26dot6 distance; \
6884 \
6885 p1 = POP (); \
6886 p2 = POP (); \
6887 \
6888 distance \
6889 = sfnt_measure_distance (interpreter, \
6890 p1, p2, \
6891 opcode); \
6892 PUSH (distance); \
6893 }
6894
6741 6895
6742 6896
6743#define NOT_IMPLEMENTED() \ 6897#define NOT_IMPLEMENTED() \
@@ -6787,14 +6941,15 @@ sfnt_interpret_utp (struct sfnt_interpreter *interpreter,
6787 interpreter->glyph_zone->flags[p] &= ~SFNT_POINT_TOUCHED_X; 6941 interpreter->glyph_zone->flags[p] &= ~SFNT_POINT_TOUCHED_X;
6788} 6942}
6789 6943
6790/* Save the specified unit VECTOR into INTERPRETER's graphics 6944/* Save the specified unit VECTOR into INTERPRETER's graphics state as
6791 state. */ 6945 both the projection and the dual projection vectors. */
6792 6946
6793static void 6947static void
6794sfnt_save_projection_vector (struct sfnt_interpreter *interpreter, 6948sfnt_save_projection_vector (struct sfnt_interpreter *interpreter,
6795 struct sfnt_unit_vector *vector) 6949 struct sfnt_unit_vector *vector)
6796{ 6950{
6797 interpreter->state.projection_vector = *vector; 6951 interpreter->state.projection_vector = *vector;
6952 interpreter->state.dual_projection_vector = *vector;
6798 6953
6799 sfnt_validate_gs (&interpreter->state); 6954 sfnt_validate_gs (&interpreter->state);
6800} 6955}
@@ -7034,6 +7189,22 @@ sfnt_check_zp2 (struct sfnt_interpreter *interpreter, uint32_t point)
7034 TRAP ("point lies outside glyph zone (ZP2)"); 7189 TRAP ("point lies outside glyph zone (ZP2)");
7035} 7190}
7036 7191
7192/* Check that the specified POINT lies within the zone addressed by
7193 INTERPRETER's ZP0 register. Trap if it does not. */
7194
7195static void
7196sfnt_check_zp0 (struct sfnt_interpreter *interpreter, uint32_t point)
7197{
7198 if (!interpreter->state.zp0)
7199 {
7200 if (point >= interpreter->twilight_zone_size)
7201 TRAP ("point lies outside twilight zone (ZP0)");
7202 }
7203 else if (!interpreter->glyph_zone
7204 || point >= interpreter->glyph_zone->num_points)
7205 TRAP ("point lies outside glyph zone (ZP0)");
7206}
7207
7037/* Move N points starting from the specified POINT in the zone 7208/* Move N points starting from the specified POINT in the zone
7038 addressed by INTERPRETER's ZP0 register by the given DISTANCE along 7209 addressed by INTERPRETER's ZP0 register by the given DISTANCE along
7039 the freedom vector. 7210 the freedom vector.
@@ -7175,6 +7346,147 @@ sfnt_project_vector (struct sfnt_interpreter *interpreter,
7175 return interpreter->state.project (vx, vy, interpreter); 7346 return interpreter->state.project (vx, vy, interpreter);
7176} 7347}
7177 7348
7349/* Project the vector VX, VY onto INTERPRETER's dual projection
7350 vector. Return the magnitude of the projection. */
7351
7352static sfnt_f26dot6
7353sfnt_dual_project_vector (struct sfnt_interpreter *interpreter,
7354 sfnt_f26dot6 vx, sfnt_f26dot6 vy)
7355{
7356 return interpreter->state.dual_project (vx, vy, interpreter);
7357}
7358
7359/* Interpret an SCFS instruction.
7360 Move P in ZP2 along the freedom vector until its projection is
7361 equal to C. */
7362
7363static void
7364sfnt_interpret_scfs (struct sfnt_interpreter *interpreter,
7365 uint32_t p, sfnt_f26dot6 c)
7366{
7367 sfnt_f26dot6 x, y, distance;
7368
7369 sfnt_address_zp2 (interpreter, p, &x, &y, NULL, NULL);
7370 distance = PROJECT (x, y);
7371 sfnt_move_zp2 (interpreter, p, 1, sfnt_sub (c, distance));
7372}
7373
7374/* Symmetrically round the 26.6 fixed point value X using the rounding
7375 mode in INTERPRETER. Return the result. */
7376
7377static sfnt_f26dot6
7378sfnt_round_symmetric (struct sfnt_interpreter *interpreter, sfnt_f26dot6 x)
7379{
7380 int sign;
7381
7382 sign = 1;
7383
7384 if (x < 0)
7385 {
7386 sign = -1;
7387 x = -x;
7388 }
7389
7390 return interpreter->state.round (x, interpreter) * sign;
7391}
7392
7393/* Interpret an MIAP (``Move Indirect Absolute Point'') instruction
7394 using INTERPRETER.
7395
7396 Move P in ZP0 along the freedom vector until its projection on the
7397 projection vector is equal to CVT units in the projection vector.
7398
7399 Finally, set RP0 and RP1 to P.
7400
7401 If OPCODE is 0x3f, then in addition check the CVT value against the
7402 control value cut-in, and round the magnitudes of the movement. */
7403
7404static void
7405sfnt_interpret_miap (struct sfnt_interpreter *interpreter,
7406 uint32_t cvt, uint32_t p, unsigned char opcode)
7407{
7408 sfnt_f26dot6 x, y, distance, value, delta;
7409
7410 sfnt_address_zp0 (interpreter, p, &x, &y, NULL, NULL);
7411
7412 /* Read the cvt value. */
7413
7414 if (cvt >= interpreter->cvt_size)
7415 TRAP ("out of bounds read to cvt");
7416
7417 value = interpreter->cvt[cvt];
7418
7419 /* Obtain the original distance. */
7420 distance = sfnt_project_vector (interpreter, x, y);
7421
7422 /* Round the distance and apply the cvt cut in if necessary. */
7423
7424 if (opcode == 0x3f)
7425 {
7426 delta = sfnt_sub (value, distance);
7427
7428 if (delta < 0)
7429 delta = -delta;
7430
7431 /* If delta is more than the cvt cut in (more aptly named ``cut
7432 out''), use the original distance. */
7433
7434 if (delta > interpreter->state.cvt_cut_in)
7435 value = distance;
7436
7437 /* Round value. */
7438 value = sfnt_round_symmetric (interpreter, value);
7439 }
7440
7441 /* Move the point by the distance. */
7442 sfnt_move_zp0 (interpreter, p, 1, sfnt_sub (value, distance));
7443
7444 /* Set reference points. */
7445 interpreter->state.rp0 = p;
7446 interpreter->state.rp1 = p;
7447}
7448
7449/* Perform a single iteration of sfnt_interpret_alignrp. RP0X and
7450 RP0Y should be the position of the reference point RP0 in ZP0. */
7451
7452static void
7453sfnt_interpret_alignrp_1 (struct sfnt_interpreter *interpreter,
7454 sfnt_f26dot6 rp0x, sfnt_f26dot6 rp0y)
7455{
7456 sfnt_f26dot6 distance, x, y;
7457 uint32_t point;
7458
7459 point = POP ();
7460
7461 /* Load this point. */
7462 sfnt_address_zp1 (interpreter, point, &x, &y, NULL, NULL);
7463
7464 /* Measure the distance from here to rp0. */
7465 distance = sfnt_project_vector (interpreter, sfnt_sub (x, rp0x),
7466 sfnt_sub (y, rp0y));
7467
7468 /* Move by the opposite. */
7469 sfnt_move_zp1 (interpreter, point, 1, -distance);
7470}
7471
7472/* For loop times, pop a point in ZP1 and align it to RP0 in ZP0 by
7473 moving it along the freedom vector until its projected distance
7474 from RP0 becomes 0. */
7475
7476static void
7477sfnt_interpret_alignrp (struct sfnt_interpreter *interpreter)
7478{
7479 sfnt_f26dot6 rp0x, rp0y;
7480
7481 sfnt_address_zp0 (interpreter, interpreter->state.rp0,
7482 &rp0x, &rp0y, NULL, NULL);
7483
7484 while (interpreter->state.loop--)
7485 sfnt_interpret_alignrp_1 (interpreter, rp0x, rp0y);
7486
7487 interpreter->state.loop = 1;
7488}
7489
7178/* Align the two points P1 and P2 relative to the projection vector. 7490/* Align the two points P1 and P2 relative to the projection vector.
7179 P1 is addressed relative to ZP0, and P2 is addressed relative to 7491 P1 is addressed relative to ZP0, and P2 is addressed relative to
7180 ZP1. 7492 ZP1.
@@ -7468,14 +7780,184 @@ sfnt_line_to_vector (struct sfnt_interpreter *interpreter,
7468 sfnt_normalize_vector (a, b, vector); 7780 sfnt_normalize_vector (a, b, vector);
7469} 7781}
7470 7782
7783/* Measure the distance between P1 in ZP0 and P2 in ZP1,
7784 relative to the projection or dual projection vector.
7785
7786 Return the distance of P1 and P2 relative to their original
7787 un-instructed positions should OPCODE be 0x49, and to their
7788 instructed positions should OPCODE be 0x4A. */
7789
7790static sfnt_f26dot6
7791sfnt_measure_distance (struct sfnt_interpreter *interpreter,
7792 uint32_t p1, uint32_t p2,
7793 unsigned char opcode)
7794{
7795 sfnt_f26dot6 p1x, p1y, p1_original_x, p1_original_y;
7796 sfnt_f26dot6 p2x, p2y, p2_original_x, p2_original_y;
7797
7798 /* P1 is relative to ZP0 and P2 is relative to ZP1.
7799 Apple's manual says this, Microsoft's does not. */
7800
7801 sfnt_address_zp0 (interpreter, p1, &p1x, &p1y,
7802 &p1_original_x, &p1_original_y);
7803 sfnt_address_zp1 (interpreter, p2, &p2x, &p2y,
7804 &p2_original_x, &p2_original_y);
7805
7806 if (opcode == 0x49)
7807 {
7808 /* When measuring in the glyph zone, measure the distance using
7809 the dual projection vector, relative to the ``original
7810 original outlines''.
7811
7812 This is not written down anywhere, leading you to believe
7813 that the distance is measured using the scaled outline prior
7814 to instructing. */
7815
7816 if (interpreter->state.zp0 == 1
7817 && interpreter->state.zp1 == 1)
7818 return sfnt_div_fixed (DUAL_PROJECT (sfnt_sub (p1x, p2x),
7819 sfnt_sub (p1y, p2y)),
7820 interpreter->scale);
7821
7822 return DUAL_PROJECT (sfnt_sub (p1x, p2x),
7823 sfnt_sub (p1y, p2y));
7824 }
7825
7826 return PROJECT (sfnt_sub (p1x, p2x),
7827 sfnt_sub (p1y, p2y));
7828}
7829
7830/* Interpret an MSIRP instruction in INTERPRETER.
7831 Take a point P, and make the distance between P in ZP1 and the
7832 current position of RP0 in ZP0 equal to D.
7833
7834 Then, if OPCODE is equal to 0x3b, make P RP0. */
7835
7836static void
7837sfnt_interpret_msirp (struct sfnt_interpreter *interpreter,
7838 uint32_t p, sfnt_f26dot6 d, unsigned char opcode)
7839{
7840 sfnt_f26dot6 rp0x, rp0y;
7841 sfnt_f26dot6 x, y;
7842 sfnt_f26dot6 old_distance;
7843
7844 sfnt_address_zp0 (interpreter, interpreter->state.rp0,
7845 &rp0x, &rp0y, NULL, NULL);
7846 sfnt_address_zp1 (interpreter, p, &x, &y, NULL, NULL);
7847
7848 /* Compute the original distance. */
7849 old_distance = sfnt_project_vector (interpreter,
7850 sfnt_sub (x, rp0x),
7851 sfnt_sub (y, rp0y));
7852
7853 /* Move the point. */
7854 sfnt_move_zp1 (interpreter, p, 1, sfnt_sub (d, old_distance));
7855
7856 /* Nothing in the TrueType reference manual says directly that this
7857 instruction should change rp1 and rp2. However, it says this
7858 instruction is ``very similar to the MIRP[] instruction
7859 except...'', and FreeType seems to do this, so do it as well. */
7860
7861 interpreter->state.rp1 = interpreter->state.rp0;
7862 interpreter->state.rp2 = p;
7863
7864 if (opcode == 0x3b)
7865 interpreter->state.rp0 = p;
7866}
7867
7868/* Interpret an IP instruction in INTERPRETER. For loop times, pop a
7869 single point in ZP2, and interpolate it so that its original
7870 relationship to the points RP1 in ZP0 and RP2 in ZP1 as measured
7871 along the dual projection vector continues to hold true. */
7872
7873static void
7874sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
7875{
7876 sfnt_f26dot6 rp1x, rp1y, rp1_original_x, rp1_original_y;
7877 sfnt_f26dot6 rp2x, rp2y, rp2_original_x, rp2_original_y;
7878 sfnt_f26dot6 range, new_range, org_distance, cur_distance;
7879 sfnt_f26dot6 new_distance;
7880 uint32_t p;
7881 sfnt_f26dot6 x, y, original_x, original_y;
7882
7883 /* First load both reference points. */
7884 sfnt_address_zp0 (interpreter, interpreter->state.rp1,
7885 &rp1x, &rp1y, &rp1_original_x,
7886 &rp1_original_y);
7887 sfnt_address_zp1 (interpreter, interpreter->state.rp2,
7888 &rp2x, &rp2y, &rp2_original_x,
7889 &rp2_original_y);
7890
7891 /* Get the original distance between of RP1 and RP2 measured
7892 relative to the dual projection vector. */
7893 range = sfnt_dual_project_vector (interpreter,
7894 sfnt_sub (rp2_original_x,
7895 rp2_original_y),
7896 sfnt_sub (rp1_original_x,
7897 rp1_original_y));
7898
7899 /* Get the new distance. */
7900 new_range = sfnt_dual_project_vector (interpreter,
7901 sfnt_sub (rp2x, rp2y),
7902 sfnt_sub (rp1x, rp1y));
7903
7904 while (interpreter->state.loop--)
7905 {
7906 p = POP ();
7907
7908 /* Load this point relative to zp2. */
7909 sfnt_address_zp2 (interpreter, p, &x, &y, &original_x,
7910 &original_y);
7911
7912 /* Now compute the old distance from this point to rp1. */
7913 org_distance
7914 = sfnt_dual_project_vector (interpreter,
7915 sfnt_sub (original_x,
7916 rp1_original_x),
7917 sfnt_sub (original_y,
7918 rp1_original_y));
7919
7920 /* And the current distance from this point to rp1, so
7921 how much to move can be determined. */
7922 cur_distance
7923 = sfnt_dual_project_vector (interpreter,
7924 sfnt_sub (x, rp1x),
7925 sfnt_sub (y, rp1y));
7926
7927 /* Finally, apply the ratio of the new distance between RP1 and
7928 RP2 to that of the old distance between the two reference
7929 points to org_distance, making new_distance.
7930
7931 If both reference points occupy the same position on the dual
7932 projection vector, then simply use the old distance. */
7933
7934 if (org_distance)
7935 {
7936 if (range)
7937 new_distance = sfnt_multiply_divide (org_distance, new_range,
7938 range);
7939 else
7940 new_distance = org_distance;
7941 }
7942 else
7943 new_distance = 0;
7944
7945 /* And move the point along the freedom vector to reflect the
7946 change in distance. */
7947 sfnt_move_zp2 (interpreter, p, 1,
7948 sfnt_sub (new_distance, cur_distance));
7949 }
7950
7951 interpreter->state.loop = 1;
7952}
7953
7471/* Apply the delta specified by OPERAND to the control value table 7954/* Apply the delta specified by OPERAND to the control value table
7472 entry at INDEX currently loaded inside INTERPRETER. 7955 entry at INDEX currently loaded inside INTERPRETER.
7473 7956
7474 Trap if INDEX is out of bounds. 7957 Trap if INDEX is out of bounds.
7475 7958
7476 NUMBER is the number of the specific DELTAC instruction this 7959 NUMBER is the number of the specific DELTAC instruction this delta
7477 instruction is being applied on behalf of. It must be between 1 7960 is being applied on behalf of. It must be between 1 and 3. */
7478 and 3. */
7479 7961
7480static void 7962static void
7481sfnt_deltac (int number, struct sfnt_interpreter *interpreter, 7963sfnt_deltac (int number, struct sfnt_interpreter *interpreter,
@@ -7612,17 +8094,19 @@ static void
7612sfnt_interpret_mdap (struct sfnt_interpreter *interpreter, 8094sfnt_interpret_mdap (struct sfnt_interpreter *interpreter,
7613 uint32_t p, uint32_t opcode) 8095 uint32_t p, uint32_t opcode)
7614{ 8096{
7615 sfnt_f26dot6 distance, px, py; 8097 sfnt_f26dot6 here, distance, px, py;
7616 8098
7617 sfnt_address_zp0 (interpreter, p, &px, &py, NULL, NULL); 8099 sfnt_address_zp0 (interpreter, p, &px, &py, NULL, NULL);
7618 8100
8101 /* Measure the current distance. */
8102 here = sfnt_project_vector (interpreter, px, py);
8103
7619 if (opcode == 0x7f) 8104 if (opcode == 0x7f)
7620 { 8105 {
7621 /* Measure distance, round, then move by distance. */ 8106 /* Measure distance, round, then move to the distance. */
7622 distance = sfnt_project_vector (interpreter, px, py); 8107 distance = sfnt_project_vector (interpreter, px, py);
7623 distance = sfnt_sub (interpreter->state.round (distance, 8108 distance = sfnt_round_symmetric (interpreter, distance);
7624 interpreter), 8109 distance = sfnt_sub (distance, here);
7625 distance);
7626 } 8110 }
7627 else 8111 else
7628 /* Don't move. Just touch the point. */ 8112 /* Don't move. Just touch the point. */
@@ -7634,6 +8118,127 @@ sfnt_interpret_mdap (struct sfnt_interpreter *interpreter,
7634 interpreter->state.rp1 = p; 8118 interpreter->state.rp1 = p;
7635} 8119}
7636 8120
8121/* Apply the delta specified by OPERAND to the point P in ZP0
8122 currently loaded inside INTERPRETER.
8123
8124 Trap if P is out of bounds.
8125
8126 NUMBER is the number of the specific DELTAP instruction this delta
8127 is being applied on behalf of. It must be between 1 and 3. */
8128
8129static void
8130sfnt_deltap (int number, struct sfnt_interpreter *interpreter,
8131 unsigned char operand, unsigned int index)
8132{
8133 int ppem, delta;
8134
8135 /* Extract the ppem from OPERAND. The format is the same as in
8136 sfnt_deltac. */
8137
8138 ppem = (operand >> 4) + interpreter->state.delta_base;
8139
8140 switch (number)
8141 {
8142 case 1:
8143 break;
8144
8145 case 2:
8146 ppem += 16;
8147 break;
8148
8149 case 3:
8150 ppem += 32;
8151 break;
8152 }
8153
8154 /* Don't apply the delta if the ppem size doesn't match. */
8155
8156 if (interpreter->ppem != ppem)
8157 return;
8158
8159 /* Now, determine the magnitude of the movement and find the
8160 delta. */
8161
8162 switch (operand & 0xf)
8163 {
8164 case 0:
8165 delta = -8;
8166 break;
8167
8168 case 1:
8169 delta = -7;
8170 break;
8171
8172 case 2:
8173 delta = -6;
8174 break;
8175
8176 case 3:
8177 delta = -5;
8178 break;
8179
8180 case 4:
8181 delta = -4;
8182 break;
8183
8184 case 5:
8185 delta = -3;
8186 break;
8187
8188 case 6:
8189 delta = -2;
8190 break;
8191
8192 case 7:
8193 delta = -1;
8194 break;
8195
8196 case 8:
8197 delta = 1;
8198 break;
8199
8200 case 9:
8201 delta = 2;
8202 break;
8203
8204 case 10:
8205 delta = 3;
8206 break;
8207
8208 case 11:
8209 delta = 4;
8210 break;
8211
8212 case 12:
8213 delta = 5;
8214 break;
8215
8216 case 13:
8217 delta = 6;
8218 break;
8219
8220 case 14:
8221 delta = 7;
8222 break;
8223
8224 case 15:
8225 delta = 8;
8226 break;
8227
8228 /* To pacify -fanalyzer. */
8229 default:
8230 abort ();
8231 }
8232
8233 /* Now, scale up the delta by the step size, which is determined by
8234 the delta shift. */
8235 delta *= 1l << (6 - interpreter->state.delta_shift);
8236
8237 /* Move the point. */
8238 sfnt_check_zp0 (interpreter, index);
8239 sfnt_move_zp0 (interpreter, index, 1, delta);
8240}
8241
7637/* Needed by sfnt_interpret_call. */ 8242/* Needed by sfnt_interpret_call. */
7638static void sfnt_interpret_run (struct sfnt_interpreter *, 8243static void sfnt_interpret_run (struct sfnt_interpreter *,
7639 enum sfnt_interpreter_run_context); 8244 enum sfnt_interpreter_run_context);
@@ -8242,6 +8847,25 @@ sfnt_project_onto_any_vector (sfnt_f26dot6 vx, sfnt_f26dot6 vy,
8242 interpreter->state.projection_vector.y); 8847 interpreter->state.projection_vector.y);
8243} 8848}
8244 8849
8850/* Project the specified vector VX and VY onto the unit vector that is
8851 INTERPRETER's dual projection vector, making only the assumption
8852 that the dual projection vector is a valid unit vector.
8853
8854 The dual projection vector is a vector that is normally the
8855 projection vector, but can be set using the original unscaled
8856 coordinates of two points as well.
8857
8858 Value is the magnitude of the projected vector. */
8859
8860static sfnt_f26dot6
8861sfnt_dual_project_onto_any_vector (sfnt_f26dot6 vx, sfnt_f26dot6 vy,
8862 struct sfnt_interpreter *interpreter)
8863{
8864 return sfnt_dot_fix_14 (vx, vy,
8865 interpreter->state.dual_projection_vector.x,
8866 interpreter->state.dual_projection_vector.y);
8867}
8868
8245/* Move N points at *X, *Y by DISTANCE along INTERPRETER's freedom 8869/* Move N points at *X, *Y by DISTANCE along INTERPRETER's freedom
8246 vector. Set *FLAGS where appropriate and when non-NULL. 8870 vector. Set *FLAGS where appropriate and when non-NULL.
8247 8871
@@ -8390,6 +9014,15 @@ sfnt_validate_gs (struct sfnt_graphics_state *gs)
8390 else 9014 else
8391 gs->project = sfnt_project_onto_any_vector; 9015 gs->project = sfnt_project_onto_any_vector;
8392 9016
9017 /* Do the same for the dual projection vector. */
9018
9019 if (gs->dual_projection_vector.x == 040000)
9020 gs->dual_project = sfnt_project_onto_x_axis_vector;
9021 else if (gs->dual_projection_vector.y == 040000)
9022 gs->dual_project = sfnt_project_onto_y_axis_vector;
9023 else
9024 gs->dual_project = sfnt_dual_project_onto_any_vector;
9025
8393 /* Compute dot product of the freedom and projection vectors. 9026 /* Compute dot product of the freedom and projection vectors.
8394 Handle the common case where the freedom vector is aligned 9027 Handle the common case where the freedom vector is aligned
8395 to an axis. */ 9028 to an axis. */
@@ -8444,6 +9077,8 @@ sfnt_set_projection_vector (struct sfnt_interpreter *interpreter,
8444{ 9077{
8445 interpreter->state.projection_vector.x = x; 9078 interpreter->state.projection_vector.x = x;
8446 interpreter->state.projection_vector.y = y; 9079 interpreter->state.projection_vector.y = y;
9080 interpreter->state.dual_projection_vector.x = x;
9081 interpreter->state.dual_projection_vector.y = y;
8447 9082
8448 sfnt_validate_gs (&interpreter->state); 9083 sfnt_validate_gs (&interpreter->state);
8449} 9084}
@@ -8574,8 +9209,8 @@ sfnt_interpret_shp (struct sfnt_interpreter *interpreter,
8574 { 9209 {
8575 point = POP (); 9210 point = POP ();
8576 9211
8577 sfnt_move_zp2 (interpreter, point, 1, magnitude);
8578 sfnt_check_zp2 (interpreter, point); 9212 sfnt_check_zp2 (interpreter, point);
9213 sfnt_move_zp2 (interpreter, point, 1, magnitude);
8579 } 9214 }
8580 9215
8581 /* Restore interpreter->state.loop to 1. */ 9216 /* Restore interpreter->state.loop to 1. */
@@ -9041,16 +9676,16 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
9041 break; 9676 break;
9042 9677
9043 case 0x39: /* IP */ 9678 case 0x39: /* IP */
9044 NOT_IMPLEMENTED (); 9679 IP ();
9045 break; 9680 break;
9046 9681
9047 case 0x3A: /* MSIRP */ 9682 case 0x3A: /* MSIRP */
9048 case 0x3B: /* MSIRP */ 9683 case 0x3B: /* MSIRP */
9049 NOT_IMPLEMENTED (); 9684 MSIRP ();
9050 break; 9685 break;
9051 9686
9052 case 0x3C: /* AlignRP */ 9687 case 0x3C: /* ALIGNRP */
9053 NOT_IMPLEMENTED (); 9688 ALIGNRP ();
9054 break; 9689 break;
9055 9690
9056 case 0x3D: /* RTDG */ 9691 case 0x3D: /* RTDG */
@@ -9059,7 +9694,7 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
9059 9694
9060 case 0x3E: /* MIAP */ 9695 case 0x3E: /* MIAP */
9061 case 0x3F: /* MIAP */ 9696 case 0x3F: /* MIAP */
9062 NOT_IMPLEMENTED (); 9697 MIAP ();
9063 break; 9698 break;
9064 9699
9065 case 0x40: /* NPUSHB */ 9700 case 0x40: /* NPUSHB */
@@ -9088,16 +9723,16 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
9088 9723
9089 case 0x46: /* GC */ 9724 case 0x46: /* GC */
9090 case 0x47: /* GC */ 9725 case 0x47: /* GC */
9091 NOT_IMPLEMENTED (); 9726 GC ();
9092 break; 9727 break;
9093 9728
9094 case 0x48: /* SCFS */ 9729 case 0x48: /* SCFS */
9095 NOT_IMPLEMENTED (); 9730 SCFS ();
9096 break; 9731 break;
9097 9732
9098 case 0x49: /* MD */ 9733 case 0x49: /* MD */
9099 case 0x4A: /* MD */ 9734 case 0x4A: /* MD */
9100 NOT_IMPLEMENTED (); 9735 MD ();
9101 break; 9736 break;
9102 9737
9103 case 0x4B: /* MPPEM */ 9738 case 0x4B: /* MPPEM */
@@ -9173,7 +9808,7 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
9173 break; 9808 break;
9174 9809
9175 case 0x5D: /* DELTAP1 */ 9810 case 0x5D: /* DELTAP1 */
9176 NOT_IMPLEMENTED (); 9811 DELTAP1 ();
9177 break; 9812 break;
9178 9813
9179 case 0x5E: /* SDB */ 9814 case 0x5E: /* SDB */
@@ -9235,8 +9870,11 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
9235 break; 9870 break;
9236 9871
9237 case 0x71: /* DELTAP2 */ 9872 case 0x71: /* DELTAP2 */
9873 DELTAP2 ();
9874 break;
9875
9238 case 0x72: /* DELTAP3 */ 9876 case 0x72: /* DELTAP3 */
9239 NOT_IMPLEMENTED (); 9877 DELTAP3 ();
9240 break; 9878 break;
9241 9879
9242 case 0x73: /* DELTAC1 */ 9880 case 0x73: /* DELTAC1 */
@@ -10108,9 +10746,10 @@ static void
10108sfnt_check_sloop (struct sfnt_interpreter *interpreter, 10746sfnt_check_sloop (struct sfnt_interpreter *interpreter,
10109 void *arg, bool trap) 10747 void *arg, bool trap)
10110{ 10748{
10111 if (interpreter->state.loop != 2) 10749 if (interpreter->state.loop != 1)
10112 { 10750 {
10113 fprintf (stderr, "failed, GS->loop should be 2, not %d\n", 10751 /* The trap should've restored GS->loop to 1. */
10752 fprintf (stderr, "failed, GS->loop should be 1, not %d\n",
10114 interpreter->state.loop); 10753 interpreter->state.loop);
10115 return; 10754 return;
10116 } 10755 }
@@ -12764,7 +13403,7 @@ main (int argc, char **argv)
12764 for (i = 0; i < table->num_subtables; ++i) 13403 for (i = 0; i < table->num_subtables; ++i)
12765 { 13404 {
12766 fprintf (stderr, "Found cmap table %"PRIu32": %p\n", 13405 fprintf (stderr, "Found cmap table %"PRIu32": %p\n",
12767 subtables[i].offset, data[i]); 13406 subtables[i].offset, (void *) data[i]);
12768 13407
12769 if (data[i]) 13408 if (data[i])
12770 fprintf (stderr, " format: %"PRIu16"\n", 13409 fprintf (stderr, " format: %"PRIu16"\n",