diff options
| author | Po Lu | 2023-02-05 20:49:19 +0800 |
|---|---|---|
| committer | Po Lu | 2023-02-05 20:49:19 +0800 |
| commit | 87cdbbeb8a229926277578a9f5f958438e8679b6 (patch) | |
| tree | 5b0b7ff3d5ab27488553a9527af715687758ea79 /src | |
| parent | 420533a8f9b345699dad9eeafeb3ccecfed516b2 (diff) | |
| download | emacs-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.c | 693 |
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 | ||
| 3 | Copyright (C) 2023 Free Software Foundation, Inc. | 3 | Copyright (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 | ||
| 6793 | static void | 6947 | static void |
| 6794 | sfnt_save_projection_vector (struct sfnt_interpreter *interpreter, | 6948 | sfnt_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 | |||
| 7195 | static void | ||
| 7196 | sfnt_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 | |||
| 7352 | static sfnt_f26dot6 | ||
| 7353 | sfnt_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 | |||
| 7363 | static void | ||
| 7364 | sfnt_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 | |||
| 7377 | static sfnt_f26dot6 | ||
| 7378 | sfnt_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 | |||
| 7404 | static void | ||
| 7405 | sfnt_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 | |||
| 7452 | static void | ||
| 7453 | sfnt_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 | |||
| 7476 | static void | ||
| 7477 | sfnt_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 | |||
| 7790 | static sfnt_f26dot6 | ||
| 7791 | sfnt_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 | |||
| 7836 | static void | ||
| 7837 | sfnt_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 | |||
| 7873 | static void | ||
| 7874 | sfnt_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 | ||
| 7480 | static void | 7962 | static void |
| 7481 | sfnt_deltac (int number, struct sfnt_interpreter *interpreter, | 7963 | sfnt_deltac (int number, struct sfnt_interpreter *interpreter, |
| @@ -7612,17 +8094,19 @@ static void | |||
| 7612 | sfnt_interpret_mdap (struct sfnt_interpreter *interpreter, | 8094 | sfnt_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 | |||
| 8129 | static void | ||
| 8130 | sfnt_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. */ |
| 7638 | static void sfnt_interpret_run (struct sfnt_interpreter *, | 8243 | static 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 | |||
| 8860 | static sfnt_f26dot6 | ||
| 8861 | sfnt_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 | |||
| 10108 | sfnt_check_sloop (struct sfnt_interpreter *interpreter, | 10746 | sfnt_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", |