aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2023-02-06 21:19:04 +0800
committerPo Lu2023-02-06 21:19:04 +0800
commit7275e32d0b0db412d6a20b3d656ef72ea72d8a44 (patch)
treec6dd2c925198c92b3b68d04f0c8b001cc5c00422
parent98c90135fe5f3729a3fa6e9a724d04a78b2cd514 (diff)
downloademacs-7275e32d0b0db412d6a20b3d656ef72ea72d8a44.tar.gz
emacs-7275e32d0b0db412d6a20b3d656ef72ea72d8a44.zip
Update Android port
* src/sfnt.c (struct sfnt_build_glyph_outline_context) (sfnt_build_glyph_outline, sfnt_fill_span): Improve glyph appearance by rounding coordinate values. (struct sfnt_interpreter): New fields `twilight_original_x', `twilight_original_y'. (sfnt_make_interpreter): Set new fields. (DELTAP1, DELTAP2, DELTAP3, SVTCAy, SPVTL, SFVTL, MD): Implement instructions. (sfnt_save_projection_vector): New argument `dual_only'. All callers changed. (sfnt_address_zp2, sfnt_address_zp1, sfnt_address_zp0): Obtain original positions in the twilight zone as well. (sfnt_check_zp1, sfnt_interpret_fliprgoff, sfnt_interpret_fliprgon) (sfnt_interpret_flippt, sfnt_interpret_scfs, sfnt_interpret_miap) (sfnt_interpret_alignrp, sfnt_line_to_vector, P) (sfnt_interpret_msirp, sfnt_interpret_ip, sfnt_interpret_call) (load_point, sfnt_interpret_iup_1, sfnt_interpret_iup) (sfnt_interpret_run, struct sfnt_scaled_outline) (struct sfnt_instructed_outline, sfnt_decompose_instructed_outline) (sfnt_build_instructed_outline, sfnt_compute_phantom_points) (sfnt_interpret_simple_glyph, all_tests, sfnt_setup_debugger) (sfnt_name_instruction, sfnt_draw_debugger, sfnt_run_hook) (sfnt_verbose, main): Make glyph instructing work. * src/sfnt.h (SFNT_POLY_ROUND): New enumerator.
-rw-r--r--src/sfnt.c1646
-rw-r--r--src/sfnt.h1
2 files changed, 1442 insertions, 205 deletions
diff --git a/src/sfnt.c b/src/sfnt.c
index 6d060fde7df..124185a5073 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -43,6 +43,10 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
43 43
44#include <time.h> 44#include <time.h>
45#include <timespec.h> 45#include <timespec.h>
46#include <sys/wait.h>
47#include <errno.h>
48
49#include <X11/Xlib.h>
46 50
47static void * 51static void *
48xmalloc (size_t size) 52xmalloc (size_t size)
@@ -2711,7 +2715,7 @@ sfnt_lerp_half (struct sfnt_point *control1, struct sfnt_point *control2,
2711 return whether or not FREE_PROC will be called with the glyph after 2715 return whether or not FREE_PROC will be called with the glyph after
2712 sfnt_decompose_glyph is done with it. 2716 sfnt_decompose_glyph is done with it.
2713 2717
2714 Both functions will be called with DCONTEXT as an argument. 2718 All functions will be called with DCONTEXT as an argument.
2715 2719
2716 The winding rule used to fill the resulting lines is described in 2720 The winding rule used to fill the resulting lines is described in
2717 chapter 2 of the TrueType reference manual, under the heading 2721 chapter 2 of the TrueType reference manual, under the heading
@@ -3008,13 +3012,6 @@ struct sfnt_build_glyph_outline_context
3008 /* The outline being built. */ 3012 /* The outline being built. */
3009 struct sfnt_glyph_outline *outline; 3013 struct sfnt_glyph_outline *outline;
3010 3014
3011 /* The head table. */
3012 struct sfnt_head_table *head;
3013
3014 /* The pixel size being used, and any extra flags to apply to the
3015 outline at this point. */
3016 int pixel_size;
3017
3018 /* Factor to multiply positions by to get the pixel width. */ 3015 /* Factor to multiply positions by to get the pixel width. */
3019 sfnt_fixed factor; 3016 sfnt_fixed factor;
3020 3017
@@ -3473,8 +3470,6 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph,
3473 variables must be used to communicate with the decomposition 3470 variables must be used to communicate with the decomposition
3474 functions. */ 3471 functions. */
3475 build_outline_context.outline = outline; 3472 build_outline_context.outline = outline;
3476 build_outline_context.head = head;
3477 build_outline_context.pixel_size = pixel_size;
3478 3473
3479 /* Clear outline bounding box. */ 3474 /* Clear outline bounding box. */
3480 outline->xmin = 0; 3475 outline->xmin = 0;
@@ -3860,6 +3855,11 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y,
3860 if (x1 <= x0) 3855 if (x1 <= x0)
3861 return; 3856 return;
3862 3857
3858 /* Round Y, X0 and X1. */
3859 y += SFNT_POLY_ROUND;
3860 x0 += SFNT_POLY_ROUND;
3861 x1 += SFNT_POLY_ROUND;
3862
3863 /* Figure out coverage based on Y axis fractional. */ 3863 /* Figure out coverage based on Y axis fractional. */
3864 coverage = sfnt_poly_coverage[(y >> (16 - SFNT_POLY_SHIFT)) 3864 coverage = sfnt_poly_coverage[(y >> (16 - SFNT_POLY_SHIFT))
3865 & SFNT_POLY_MASK]; 3865 & SFNT_POLY_MASK];
@@ -5093,6 +5093,16 @@ struct sfnt_interpreter
5093 /* The twilight zone. May not be NULL. */ 5093 /* The twilight zone. May not be NULL. */
5094 sfnt_f26dot6 *restrict twilight_x, *restrict twilight_y; 5094 sfnt_f26dot6 *restrict twilight_x, *restrict twilight_y;
5095 5095
5096 /* The original X positions of points in the twilight zone. */
5097 sfnt_f26dot6 *restrict twilight_original_x;
5098
5099 /* The original Y positions of points in the twilight zone.
5100
5101 Apple does not directly say whether or not points in the twilight
5102 zone can have their original positions changed. But this is
5103 implied by ``create points in the twilight zone''. */
5104 sfnt_f26dot6 *restrict twilight_original_y;
5105
5096 /* The scaled outlines being manipulated. May be NULL. */ 5106 /* The scaled outlines being manipulated. May be NULL. */
5097 struct sfnt_interpreter_zone *glyph_zone; 5107 struct sfnt_interpreter_zone *glyph_zone;
5098 5108
@@ -5133,6 +5143,12 @@ struct sfnt_interpreter
5133 5143
5134 /* What was the trap. */ 5144 /* What was the trap. */
5135 const char *trap_reason; 5145 const char *trap_reason;
5146
5147#ifdef TEST
5148 /* If non-NULL, function called before each instruction is
5149 executed. */
5150 void (*run_hook) (struct sfnt_interpreter *);
5151#endif
5136}; 5152};
5137 5153
5138/* Divide the specified two 26.6 fixed point numbers X and Y. 5154/* Divide the specified two 26.6 fixed point numbers X and Y.
@@ -5351,6 +5367,16 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
5351 size, &size)) 5367 size, &size))
5352 return NULL; 5368 return NULL;
5353 5369
5370 if (INT_ADD_WRAPV ((maxp->max_twilight_points
5371 * sizeof *interpreter->twilight_y),
5372 size, &size))
5373 return NULL;
5374
5375 if (INT_ADD_WRAPV ((maxp->max_twilight_points
5376 * sizeof *interpreter->twilight_y),
5377 size, &size))
5378 return NULL;
5379
5354 /* Add the storage area. */ 5380 /* Add the storage area. */
5355 storage_size = maxp->max_storage * sizeof *interpreter->storage; 5381 storage_size = maxp->max_storage * sizeof *interpreter->storage;
5356 if (INT_ADD_WRAPV (storage_size, size, &size)) 5382 if (INT_ADD_WRAPV (storage_size, size, &size))
@@ -5383,6 +5409,10 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
5383 /* Allocate the interpreter. */ 5409 /* Allocate the interpreter. */
5384 interpreter = xmalloc (size); 5410 interpreter = xmalloc (size);
5385 5411
5412#ifdef TEST
5413 interpreter->run_hook = NULL;
5414#endif
5415
5386 /* Fill in pointers and default values. */ 5416 /* Fill in pointers and default values. */
5387 interpreter->max_stack_elements = maxp->max_stack_elements; 5417 interpreter->max_stack_elements = maxp->max_stack_elements;
5388 interpreter->num_instructions = 0; 5418 interpreter->num_instructions = 0;
@@ -5401,10 +5431,15 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
5401 + maxp->max_stack_elements); 5431 + maxp->max_stack_elements);
5402 interpreter->twilight_y = (interpreter->twilight_x 5432 interpreter->twilight_y = (interpreter->twilight_x
5403 + maxp->max_twilight_points); 5433 + maxp->max_twilight_points);
5434 interpreter->twilight_original_x = (interpreter->twilight_y
5435 + maxp->max_twilight_points);
5436 interpreter->twilight_original_y
5437 = (interpreter->twilight_original_x
5438 + maxp->max_twilight_points);
5404 interpreter->glyph_zone = NULL; 5439 interpreter->glyph_zone = NULL;
5405 interpreter->advance_width = 0; 5440 interpreter->advance_width = 0;
5406 interpreter->storage 5441 interpreter->storage
5407 = (uint32_t *) (interpreter->twilight_y 5442 = (uint32_t *) (interpreter->twilight_original_y
5408 + maxp->max_twilight_points); 5443 + maxp->max_twilight_points);
5409 interpreter->function_defs 5444 interpreter->function_defs
5410 = (struct sfnt_interpreter_definition *) (interpreter->storage 5445 = (struct sfnt_interpreter_definition *) (interpreter->storage
@@ -6537,6 +6572,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6537 argn = POP (); \ 6572 argn = POP (); \
6538 pn = POP (); \ 6573 pn = POP (); \
6539 sfnt_deltap (1, interpreter, argn, pn); \ 6574 sfnt_deltap (1, interpreter, argn, pn); \
6575 n--; \
6540 goto deltap1_start; \ 6576 goto deltap1_start; \
6541 } 6577 }
6542 6578
@@ -6553,6 +6589,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6553 argn = POP (); \ 6589 argn = POP (); \
6554 pn = POP (); \ 6590 pn = POP (); \
6555 sfnt_deltap (2, interpreter, argn, pn); \ 6591 sfnt_deltap (2, interpreter, argn, pn); \
6592 n--; \
6556 goto deltap2_start; \ 6593 goto deltap2_start; \
6557 } 6594 }
6558 6595
@@ -6569,6 +6606,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6569 argn = POP (); \ 6606 argn = POP (); \
6570 pn = POP (); \ 6607 pn = POP (); \
6571 sfnt_deltap (3, interpreter, argn, pn); \ 6608 sfnt_deltap (3, interpreter, argn, pn); \
6609 n--; \
6572 goto deltap3_start; \ 6610 goto deltap3_start; \
6573 } 6611 }
6574 6612
@@ -6599,41 +6637,41 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6599#define SVTCAy() \ 6637#define SVTCAy() \
6600 { \ 6638 { \
6601 sfnt_set_freedom_vector (interpreter, \ 6639 sfnt_set_freedom_vector (interpreter, \
6602 040000, 0); \ 6640 0, 040000); \
6603 sfnt_set_projection_vector (interpreter, \ 6641 sfnt_set_projection_vector (interpreter, \
6604 040000, 0); \ 6642 0, 040000); \
6605 } 6643 }
6606 6644
6607#define SVTCAx() \ 6645#define SVTCAx() \
6608 { \ 6646 { \
6609 sfnt_set_freedom_vector (interpreter, 0, \ 6647 sfnt_set_freedom_vector (interpreter, \
6610 040000); \ 6648 040000, 0); \
6611 sfnt_set_projection_vector (interpreter, 0, \ 6649 sfnt_set_projection_vector (interpreter, \
6612 040000); \ 6650 040000, 0); \
6613 } 6651 }
6614 6652
6615#define SPvTCAy() \ 6653#define SPvTCAy() \
6616 { \ 6654 { \
6617 sfnt_set_projection_vector (interpreter, \ 6655 sfnt_set_projection_vector (interpreter, \
6618 040000, 0); \ 6656 0, 040000); \
6619 } 6657 }
6620 6658
6621#define SPvTCAx() \ 6659#define SPvTCAx() \
6622 { \ 6660 { \
6623 sfnt_set_projection_vector (interpreter, 0, \ 6661 sfnt_set_projection_vector (interpreter, \
6624 040000); \ 6662 040000, 0); \
6625 } 6663 }
6626 6664
6627#define SFvTCAy() \ 6665#define SFvTCAy() \
6628 { \ 6666 { \
6629 sfnt_set_freedom_vector (interpreter, \ 6667 sfnt_set_freedom_vector (interpreter, \
6630 040000, 0); \ 6668 0, 040000); \
6631 } 6669 }
6632 6670
6633#define SFvTCAx() \ 6671#define SFvTCAx() \
6634 { \ 6672 { \
6635 sfnt_set_freedom_vector (interpreter, 0, \ 6673 sfnt_set_freedom_vector (interpreter, \
6636 040000); \ 6674 040000, 0); \
6637 } 6675 }
6638 6676
6639#define SPVTL() \ 6677#define SPVTL() \
@@ -6646,10 +6684,12 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6646 \ 6684 \
6647 sfnt_line_to_vector (interpreter, \ 6685 sfnt_line_to_vector (interpreter, \
6648 p2, p1, &vector, \ 6686 p2, p1, &vector, \
6649 opcode == 0x07); \ 6687 opcode == 0x07, \
6688 false); \
6650 \ 6689 \
6651 sfnt_save_projection_vector (interpreter, \ 6690 sfnt_save_projection_vector (interpreter, \
6652 &vector); \ 6691 &vector, \
6692 false); \
6653 } 6693 }
6654 6694
6655#define SFVTL() \ 6695#define SFVTL() \
@@ -6662,7 +6702,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6662 \ 6702 \
6663 sfnt_line_to_vector (interpreter, \ 6703 sfnt_line_to_vector (interpreter, \
6664 p2, p1, &vector, \ 6704 p2, p1, &vector, \
6665 opcode == 0x09); \ 6705 opcode == 0x09, \
6706 false); \
6666 \ 6707 \
6667 sfnt_save_freedom_vector (interpreter, \ 6708 sfnt_save_freedom_vector (interpreter, \
6668 &vector); \ 6709 &vector); \
@@ -6892,6 +6933,70 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
6892 PUSH (distance); \ 6933 PUSH (distance); \
6893 } 6934 }
6894 6935
6936#define FLIPPT() \
6937 { \
6938 sfnt_interpret_flippt (interpreter); \
6939 }
6940
6941#define FLIPRGOFF() \
6942 { \
6943 uint32_t h, l; \
6944 \
6945 h = POP (); \
6946 l = POP (); \
6947 \
6948 sfnt_interpret_fliprgoff (interpreter, \
6949 h, l); \
6950 }
6951
6952#define FLIPRGON() \
6953 { \
6954 uint32_t h, l; \
6955 \
6956 h = POP (); \
6957 l = POP (); \
6958 \
6959 sfnt_interpret_fliprgon (interpreter, \
6960 h, l); \
6961 }
6962
6963#define SDPVTL() \
6964 { \
6965 struct sfnt_unit_vector vector; \
6966 uint32_t p2, p1; \
6967 \
6968 p2 = POP (); \
6969 p1 = POP (); \
6970 \
6971 sfnt_line_to_vector (interpreter, \
6972 p2, p1, &vector, \
6973 opcode == 0x87, \
6974 false); \
6975 \
6976 sfnt_save_projection_vector (interpreter, \
6977 &vector, \
6978 false); \
6979 \
6980 sfnt_line_to_vector (interpreter, \
6981 p2, p1, &vector, \
6982 opcode == 0x87, \
6983 true); \
6984 \
6985 sfnt_save_projection_vector (interpreter, \
6986 &vector, \
6987 true); \
6988 }
6989
6990#define MIRP() \
6991 { \
6992 sfnt_interpret_mirp (interpreter, opcode); \
6993 }
6994
6995#define MDRP() \
6996 { \
6997 sfnt_interpret_mdrp (interpreter, opcode); \
6998 }
6999
6895 7000
6896 7001
6897#define NOT_IMPLEMENTED() \ 7002#define NOT_IMPLEMENTED() \
@@ -6942,13 +7047,20 @@ sfnt_interpret_utp (struct sfnt_interpreter *interpreter,
6942} 7047}
6943 7048
6944/* Save the specified unit VECTOR into INTERPRETER's graphics state as 7049/* Save the specified unit VECTOR into INTERPRETER's graphics state as
6945 both the projection and the dual projection vectors. */ 7050 both the projection and the dual projection vectors.
7051
7052 If not DUAL_ONLY, set VECTOR as both the projection and dual
7053 projection vectors. Otherwise, only set VECTOR as the dual
7054 projection vector. */
6946 7055
6947static void 7056static void
6948sfnt_save_projection_vector (struct sfnt_interpreter *interpreter, 7057sfnt_save_projection_vector (struct sfnt_interpreter *interpreter,
6949 struct sfnt_unit_vector *vector) 7058 struct sfnt_unit_vector *vector,
7059 bool dual_only)
6950{ 7060{
6951 interpreter->state.projection_vector = *vector; 7061 if (!dual_only)
7062 interpreter->state.projection_vector = *vector;
7063
6952 interpreter->state.dual_projection_vector = *vector; 7064 interpreter->state.dual_projection_vector = *vector;
6953 7065
6954 sfnt_validate_gs (&interpreter->state); 7066 sfnt_validate_gs (&interpreter->state);
@@ -6992,9 +7104,10 @@ sfnt_address_zp2 (struct sfnt_interpreter *interpreter,
6992 if (!x_org || !y_org) 7104 if (!x_org || !y_org)
6993 return; 7105 return;
6994 7106
6995 /* The twilight zone is initially all zero. */ 7107 /* The twilight zone is initially all zero, but initial
6996 *x_org = 0; 7108 positions can still be changed. */
6997 *y_org = 0; 7109 *x_org = interpreter->twilight_original_x[number];
7110 *y_org = interpreter->twilight_original_y[number];
6998 return; 7111 return;
6999 } 7112 }
7000 7113
@@ -7039,9 +7152,10 @@ sfnt_address_zp1 (struct sfnt_interpreter *interpreter,
7039 if (!x_org || !y_org) 7152 if (!x_org || !y_org)
7040 return; 7153 return;
7041 7154
7042 /* The twilight zone is initially all zero. */ 7155 /* The twilight zone is initially all zero, but initial
7043 *x_org = 0; 7156 positions can still be changed. */
7044 *y_org = 0; 7157 *x_org = interpreter->twilight_original_x[number];
7158 *y_org = interpreter->twilight_original_y[number];
7045 return; 7159 return;
7046 } 7160 }
7047 7161
@@ -7086,9 +7200,10 @@ sfnt_address_zp0 (struct sfnt_interpreter *interpreter,
7086 if (!x_org || !y_org) 7200 if (!x_org || !y_org)
7087 return; 7201 return;
7088 7202
7089 /* The twilight zone is initially all zero. */ 7203 /* The twilight zone is initially all zero, but initial
7090 *x_org = 0; 7204 positions can still be changed. */
7091 *y_org = 0; 7205 *x_org = interpreter->twilight_original_x[number];
7206 *y_org = interpreter->twilight_original_y[number];
7092 return; 7207 return;
7093 } 7208 }
7094 7209
@@ -7205,6 +7320,22 @@ sfnt_check_zp0 (struct sfnt_interpreter *interpreter, uint32_t point)
7205 TRAP ("point lies outside glyph zone (ZP0)"); 7320 TRAP ("point lies outside glyph zone (ZP0)");
7206} 7321}
7207 7322
7323/* Check that the specified POINT lies within the zone addressed by
7324 INTERPRETER's ZP1 register. Trap if it does not. */
7325
7326static void
7327sfnt_check_zp1 (struct sfnt_interpreter *interpreter, uint32_t point)
7328{
7329 if (!interpreter->state.zp1)
7330 {
7331 if (point >= interpreter->twilight_zone_size)
7332 TRAP ("point lies outside twilight zone (ZP0)");
7333 }
7334 else if (!interpreter->glyph_zone
7335 || point >= interpreter->glyph_zone->num_points)
7336 TRAP ("point lies outside glyph zone (ZP0)");
7337}
7338
7208/* Move N points starting from the specified POINT in the zone 7339/* Move N points starting from the specified POINT in the zone
7209 addressed by INTERPRETER's ZP0 register by the given DISTANCE along 7340 addressed by INTERPRETER's ZP0 register by the given DISTANCE along
7210 the freedom vector. 7341 the freedom vector.
@@ -7356,9 +7487,84 @@ sfnt_dual_project_vector (struct sfnt_interpreter *interpreter,
7356 return interpreter->state.dual_project (vx, vy, interpreter); 7487 return interpreter->state.dual_project (vx, vy, interpreter);
7357} 7488}
7358 7489
7490/* Interpret a FLIPRGOFF instruction in INTERPRTER. Make each point
7491 in ZP0 between L and H an off-curve point. */
7492
7493static void
7494sfnt_interpret_fliprgoff (struct sfnt_interpreter *interpreter,
7495 uint32_t l, uint32_t h)
7496{
7497 uint32_t i;
7498
7499 sfnt_check_zp0 (interpreter, l);
7500 sfnt_check_zp0 (interpreter, h);
7501
7502 if (!interpreter->state.zp0)
7503 return;
7504
7505 for (i = l; i < h; ++i)
7506 interpreter->glyph_zone->flags[i] &= ~01;
7507}
7508
7509/* Interpret a FLIPRGON instruction in INTERPRTER. Make each point in
7510 ZP0 between L and H an on-curve point. */
7511
7512static void
7513sfnt_interpret_fliprgon (struct sfnt_interpreter *interpreter,
7514 uint32_t l, uint32_t h)
7515{
7516 uint32_t i;
7517
7518 sfnt_check_zp0 (interpreter, l);
7519 sfnt_check_zp0 (interpreter, h);
7520
7521 if (!interpreter->state.zp0)
7522 return;
7523
7524 for (i = l; i < h; ++i)
7525 interpreter->glyph_zone->flags[i] |= ~01;
7526}
7527
7528/* Interpret a FLIPPT instruction in INTERPRETER. For loop times, pop
7529 a point in ZP0. If it is an on-curve point, make it an off-curve
7530 one, and vice versa. */
7531
7532static void
7533sfnt_interpret_flippt (struct sfnt_interpreter *interpreter)
7534{
7535 uint32_t point;
7536
7537 while (interpreter->state.loop--)
7538 {
7539 point = POP ();
7540
7541 /* There are no flags in the twilight zone.
7542 But first check that the point is within bounds. */
7543
7544 sfnt_check_zp0 (interpreter, point);
7545
7546 if (!interpreter->state.zp0)
7547 continue;
7548
7549 /* If POINT is on the curve, make it off the curve and vice
7550 versa. */
7551
7552 if (interpreter->glyph_zone->flags[point] & 01)
7553 interpreter->glyph_zone->flags[point] &= ~01;
7554 else
7555 interpreter->glyph_zone->flags[point] |= 01;
7556 }
7557
7558 /* Restore loop. */
7559 interpreter->state.loop = 1;
7560}
7561
7359/* Interpret an SCFS instruction. 7562/* Interpret an SCFS instruction.
7360 Move P in ZP2 along the freedom vector until its projection is 7563 Move P in ZP2 along the freedom vector until its projection is
7361 equal to C. */ 7564 equal to C.
7565
7566 If ZP2 is the twilight zone, ``create'' P by setting its original
7567 position to the projection. */
7362 7568
7363static void 7569static void
7364sfnt_interpret_scfs (struct sfnt_interpreter *interpreter, 7570sfnt_interpret_scfs (struct sfnt_interpreter *interpreter,
@@ -7369,6 +7575,14 @@ sfnt_interpret_scfs (struct sfnt_interpreter *interpreter,
7369 sfnt_address_zp2 (interpreter, p, &x, &y, NULL, NULL); 7575 sfnt_address_zp2 (interpreter, p, &x, &y, NULL, NULL);
7370 distance = PROJECT (x, y); 7576 distance = PROJECT (x, y);
7371 sfnt_move_zp2 (interpreter, p, 1, sfnt_sub (c, distance)); 7577 sfnt_move_zp2 (interpreter, p, 1, sfnt_sub (c, distance));
7578
7579 if (!interpreter->state.zp2)
7580 {
7581 interpreter->twilight_original_x[p]
7582 = interpreter->twilight_x[p];
7583 interpreter->twilight_original_y[p]
7584 = interpreter->twilight_y[p];
7585 }
7372} 7586}
7373 7587
7374/* Symmetrically round the 26.6 fixed point value X using the rounding 7588/* Symmetrically round the 26.6 fixed point value X using the rounding
@@ -7398,6 +7612,10 @@ sfnt_round_symmetric (struct sfnt_interpreter *interpreter, sfnt_f26dot6 x)
7398 7612
7399 Finally, set RP0 and RP1 to P. 7613 Finally, set RP0 and RP1 to P.
7400 7614
7615 If ZP0 is the twilight zone, then first create that point in the
7616 twilight zone by setting its ``original position'' to the
7617 projection of the value.
7618
7401 If OPCODE is 0x3f, then in addition check the CVT value against the 7619 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. */ 7620 control value cut-in, and round the magnitudes of the movement. */
7403 7621
@@ -7407,8 +7625,6 @@ sfnt_interpret_miap (struct sfnt_interpreter *interpreter,
7407{ 7625{
7408 sfnt_f26dot6 x, y, distance, value, delta; 7626 sfnt_f26dot6 x, y, distance, value, delta;
7409 7627
7410 sfnt_address_zp0 (interpreter, p, &x, &y, NULL, NULL);
7411
7412 /* Read the cvt value. */ 7628 /* Read the cvt value. */
7413 7629
7414 if (cvt >= interpreter->cvt_size) 7630 if (cvt >= interpreter->cvt_size)
@@ -7416,6 +7632,25 @@ sfnt_interpret_miap (struct sfnt_interpreter *interpreter,
7416 7632
7417 value = interpreter->cvt[cvt]; 7633 value = interpreter->cvt[cvt];
7418 7634
7635 /* Now load the point. */
7636 sfnt_address_zp0 (interpreter, p, &x, &y, NULL, NULL);
7637
7638 /* Create the twilight zone point if necessary.
7639 Note that the value used is not rounded. */
7640
7641 if (!interpreter->state.zp0)
7642 {
7643 x = interpreter->twilight_x[p]
7644 = interpreter->twilight_original_x[p]
7645 = sfnt_mul_f2dot14 (interpreter->state.projection_vector.x,
7646 value);
7647
7648 y = interpreter->twilight_y[p]
7649 = interpreter->twilight_original_y[p]
7650 = sfnt_mul_f2dot14 (interpreter->state.projection_vector.y,
7651 value);
7652 }
7653
7419 /* Obtain the original distance. */ 7654 /* Obtain the original distance. */
7420 distance = sfnt_project_vector (interpreter, x, y); 7655 distance = sfnt_project_vector (interpreter, x, y);
7421 7656
@@ -7482,7 +7717,14 @@ sfnt_interpret_alignrp (struct sfnt_interpreter *interpreter)
7482 &rp0x, &rp0y, NULL, NULL); 7717 &rp0x, &rp0y, NULL, NULL);
7483 7718
7484 while (interpreter->state.loop--) 7719 while (interpreter->state.loop--)
7485 sfnt_interpret_alignrp_1 (interpreter, rp0x, rp0y); 7720 {
7721 sfnt_interpret_alignrp_1 (interpreter, rp0x, rp0y);
7722
7723 /* Reload RP0 if it is in the same zone as ZP1. */
7724 if (interpreter->state.zp0 == interpreter->state.zp1)
7725 sfnt_address_zp0 (interpreter, interpreter->state.rp0,
7726 &rp0x, &rp0y, NULL, NULL);
7727 }
7486 7728
7487 interpreter->state.loop = 1; 7729 interpreter->state.loop = 1;
7488} 7730}
@@ -7748,20 +7990,26 @@ sfnt_normalize_vector (sfnt_f26dot6 vx, sfnt_f26dot6 vy,
7748 specified INTERPRETER's graphics state. 7990 specified INTERPRETER's graphics state.
7749 7991
7750 If PERPENDICULAR, then *VECTOR will be rotated 90 degrees 7992 If PERPENDICULAR, then *VECTOR will be rotated 90 degrees
7751 counter-clockwise. Else, *VECTOR will be parallel to the line. */ 7993 counter-clockwise. Else, *VECTOR will be parallel to the line.
7994
7995 If ORIGINAL, then the coordinates used to calculate the line will
7996 be those prior to instructing. Otherwise, the current coordinates
7997 will be used. */
7752 7998
7753static void 7999static void
7754sfnt_line_to_vector (struct sfnt_interpreter *interpreter, 8000sfnt_line_to_vector (struct sfnt_interpreter *interpreter,
7755 uint32_t p2, uint32_t p1, 8001 uint32_t p2, uint32_t p1,
7756 struct sfnt_unit_vector *vector, 8002 struct sfnt_unit_vector *vector,
7757 bool perpendicular) 8003 bool perpendicular, bool original)
7758{ 8004{
7759 sfnt_f26dot6 x2, y2; 8005 sfnt_f26dot6 x2, y2, original_x2, original_y2;
7760 sfnt_f26dot6 x1, y1; 8006 sfnt_f26dot6 x1, y1, original_x1, original_y1;
7761 sfnt_f26dot6 a, b, temp; 8007 sfnt_f26dot6 a, b, temp;
7762 8008
7763 sfnt_address_zp2 (interpreter, p2, &x2, &y2, NULL, NULL); 8009 sfnt_address_zp2 (interpreter, p2, &x2, &y2, &original_x2,
7764 sfnt_address_zp1 (interpreter, p1, &x1, &y1, NULL, NULL); 8010 &original_y2);
8011 sfnt_address_zp1 (interpreter, p1, &x1, &y1, &original_x1,
8012 &original_y1);
7765 8013
7766 /* Calculate the vector between X2, Y2, and X1, Y1. */ 8014 /* Calculate the vector between X2, Y2, and X1, Y1. */
7767 a = sfnt_sub (x1, x2); 8015 a = sfnt_sub (x1, x2);
@@ -7831,20 +8079,42 @@ sfnt_measure_distance (struct sfnt_interpreter *interpreter,
7831 Take a point P, and make the distance between P in ZP1 and the 8079 Take a point P, and make the distance between P in ZP1 and the
7832 current position of RP0 in ZP0 equal to D. 8080 current position of RP0 in ZP0 equal to D.
7833 8081
8082 If ZP1 is the twilight zone, then create the point P by setting its
8083 position and relative positions.
8084
7834 Then, if OPCODE is equal to 0x3b, make P RP0. */ 8085 Then, if OPCODE is equal to 0x3b, make P RP0. */
7835 8086
7836static void 8087static void
7837sfnt_interpret_msirp (struct sfnt_interpreter *interpreter, 8088sfnt_interpret_msirp (struct sfnt_interpreter *interpreter,
7838 uint32_t p, sfnt_f26dot6 d, unsigned char opcode) 8089 uint32_t p, sfnt_f26dot6 d, unsigned char opcode)
7839{ 8090{
7840 sfnt_f26dot6 rp0x, rp0y; 8091 sfnt_f26dot6 rp0x, rp0y, rp0_original_x, rp0_original_y;
7841 sfnt_f26dot6 x, y; 8092 sfnt_f26dot6 x, y;
7842 sfnt_f26dot6 old_distance; 8093 sfnt_f26dot6 old_distance, temp;
7843 8094
7844 sfnt_address_zp0 (interpreter, interpreter->state.rp0, 8095 sfnt_address_zp0 (interpreter, interpreter->state.rp0,
7845 &rp0x, &rp0y, NULL, NULL); 8096 &rp0x, &rp0y, &rp0_original_x,
8097 &rp0_original_y);
7846 sfnt_address_zp1 (interpreter, p, &x, &y, NULL, NULL); 8098 sfnt_address_zp1 (interpreter, p, &x, &y, NULL, NULL);
7847 8099
8100 if (!interpreter->state.zp1)
8101 {
8102 /* Create this point in the twilight zone at RP0. */
8103
8104 x = interpreter->twilight_x[p] = rp0x;
8105 y = interpreter->twilight_y[p] = rp0y;
8106
8107 /* Now set the original positions to the projected difference
8108 from rp0. This makes sense once you think about it. */
8109 temp = sfnt_mul_f2dot14 (interpreter->state.projection_vector.x, d);
8110 temp = sfnt_add (temp, rp0_original_x);
8111 interpreter->twilight_original_x[p] = temp;
8112
8113 temp = sfnt_mul_f2dot14 (interpreter->state.projection_vector.y, d);
8114 temp = sfnt_add (temp, rp0_original_y);
8115 interpreter->twilight_original_y[p] = temp;
8116 }
8117
7848 /* Compute the original distance. */ 8118 /* Compute the original distance. */
7849 old_distance = sfnt_project_vector (interpreter, 8119 old_distance = sfnt_project_vector (interpreter,
7850 sfnt_sub (x, rp0x), 8120 sfnt_sub (x, rp0x),
@@ -7892,14 +8162,14 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
7892 relative to the dual projection vector. */ 8162 relative to the dual projection vector. */
7893 range = sfnt_dual_project_vector (interpreter, 8163 range = sfnt_dual_project_vector (interpreter,
7894 sfnt_sub (rp2_original_x, 8164 sfnt_sub (rp2_original_x,
7895 rp2_original_y), 8165 rp1_original_x),
7896 sfnt_sub (rp1_original_x, 8166 sfnt_sub (rp2_original_y,
7897 rp1_original_y)); 8167 rp1_original_y));
7898 8168
7899 /* Get the new distance. */ 8169 /* Get the new distance. */
7900 new_range = sfnt_dual_project_vector (interpreter, 8170 new_range = sfnt_dual_project_vector (interpreter,
7901 sfnt_sub (rp2x, rp2y), 8171 sfnt_sub (rp2x, rp1x),
7902 sfnt_sub (rp1x, rp1y)); 8172 sfnt_sub (rp2y, rp1y));
7903 8173
7904 while (interpreter->state.loop--) 8174 while (interpreter->state.loop--)
7905 { 8175 {
@@ -7920,9 +8190,9 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
7920 /* And the current distance from this point to rp1, so 8190 /* And the current distance from this point to rp1, so
7921 how much to move can be determined. */ 8191 how much to move can be determined. */
7922 cur_distance 8192 cur_distance
7923 = sfnt_dual_project_vector (interpreter, 8193 = sfnt_project_vector (interpreter,
7924 sfnt_sub (x, rp1x), 8194 sfnt_sub (x, rp1x),
7925 sfnt_sub (y, rp1y)); 8195 sfnt_sub (y, rp1y));
7926 8196
7927 /* Finally, apply the ratio of the new distance between RP1 and 8197 /* Finally, apply the ratio of the new distance between RP1 and
7928 RP2 to that of the old distance between the two reference 8198 RP2 to that of the old distance between the two reference
@@ -7934,8 +8204,9 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter)
7934 if (org_distance) 8204 if (org_distance)
7935 { 8205 {
7936 if (range) 8206 if (range)
7937 new_distance = sfnt_multiply_divide (org_distance, new_range, 8207 new_distance
7938 range); 8208 = sfnt_multiply_divide_signed (org_distance,
8209 new_range, range);
7939 else 8210 else
7940 new_distance = org_distance; 8211 new_distance = org_distance;
7941 } 8212 }
@@ -8263,8 +8534,8 @@ sfnt_interpret_call (struct sfnt_interpreter_definition *definition,
8263 unsigned char *instructions; 8534 unsigned char *instructions;
8264 8535
8265 /* Check that no recursion is going on. */ 8536 /* Check that no recursion is going on. */
8266 if (interpreter->call_depth++ >= 64) 8537 if (interpreter->call_depth++ >= 128)
8267 TRAP ("CALL called CALL more than 63 times"); 8538 TRAP ("CALL called CALL more than 127 times");
8268 8539
8269 /* Save the old IP, instructions and number of instructions. */ 8540 /* Save the old IP, instructions and number of instructions. */
8270 num_instructions = interpreter->num_instructions; 8541 num_instructions = interpreter->num_instructions;
@@ -8274,7 +8545,6 @@ sfnt_interpret_call (struct sfnt_interpreter_definition *definition,
8274 /* Load and run the definition. */ 8545 /* Load and run the definition. */
8275 interpreter->num_instructions = definition->instruction_count; 8546 interpreter->num_instructions = definition->instruction_count;
8276 interpreter->instructions = definition->instructions; 8547 interpreter->instructions = definition->instructions;
8277 interpreter->glyph_zone = NULL;
8278 interpreter->IP = 0; 8548 interpreter->IP = 0;
8279 sfnt_interpret_run (interpreter, context); 8549 sfnt_interpret_run (interpreter, context);
8280 8550
@@ -8282,6 +8552,7 @@ sfnt_interpret_call (struct sfnt_interpreter_definition *definition,
8282 interpreter->num_instructions = num_instructions; 8552 interpreter->num_instructions = num_instructions;
8283 interpreter->IP = IP; 8553 interpreter->IP = IP;
8284 interpreter->instructions = instructions; 8554 interpreter->instructions = instructions;
8555 interpreter->call_depth--;
8285} 8556}
8286 8557
8287/* Set the detailed rounding state in interpreter, on behalf of either 8558/* Set the detailed rounding state in interpreter, on behalf of either
@@ -9217,6 +9488,93 @@ sfnt_interpret_shp (struct sfnt_interpreter *interpreter,
9217 interpreter->state.loop = 1; 9488 interpreter->state.loop = 1;
9218} 9489}
9219 9490
9491#define load_point(p) \
9492 (opcode == 0x31 \
9493 ? interpreter->glyph_zone->x_current[p] \
9494 : interpreter->glyph_zone->y_current[p])
9495
9496#define store_point(p, val) \
9497 (opcode == 0x31 \
9498 ? (interpreter->glyph_zone->x_current[p] = (val)) \
9499 : (interpreter->glyph_zone->y_current[p] = (val)))
9500
9501#define load_original(p) \
9502 (opcode == 0x31 \
9503 ? interpreter->glyph_zone->x_points[p] \
9504 : interpreter->glyph_zone->y_points[p])
9505
9506#define IUP_SINGLE_PAIR() \
9507 /* Now make touch_start the first point before, i.e. the first \
9508 touched point in this pair. */ \
9509 \
9510 if (touch_start == start) \
9511 touch_start = end; \
9512 else \
9513 touch_start = touch_start - 1; \
9514 \
9515 /* Set point_min and point_max based on which glyph is at a \
9516 lower value. */ \
9517 \
9518 if (load_original (touch_start) < load_original (touch_end)) \
9519 { \
9520 point_min = touch_start; \
9521 point_max = touch_end; \
9522 } \
9523 else \
9524 { \
9525 point_max = touch_start; \
9526 point_min = touch_end; \
9527 } \
9528 \
9529 min_pos = load_point (point_min); \
9530 max_pos = load_point (point_max); \
9531 \
9532 /* This is needed for interpolation. */ \
9533 original_max_pos = load_original (point_max); \
9534 original_min_pos = load_original (point_min); \
9535 \
9536 /* Now process points between touch_start and touch_end. */ \
9537 \
9538 i = touch_start + 1; \
9539 \
9540 for (; i <= end; ++i) \
9541 { \
9542 if (i > end) \
9543 i = start; \
9544 \
9545 /* Movement is always relative to the original position of \
9546 the point. */ \
9547 position = load_original (i); \
9548 \
9549 /* If i is in between touch_start and touch_end... */ \
9550 if (position >= original_min_pos \
9551 && position <= original_max_pos \
9552 && original_min_pos != original_max_pos) \
9553 { \
9554 /* ... preserve the ratio of i between min_pos and \
9555 max_pos... */ \
9556 ratio = sfnt_div_fixed (sfnt_sub (position, \
9557 original_min_pos) * 1024, \
9558 sfnt_sub (original_max_pos, \
9559 original_min_pos) * 1024); \
9560 delta = sfnt_sub (max_pos, min_pos); \
9561 delta = sfnt_mul_fixed (ratio, delta); \
9562 store_point (i, sfnt_add (min_pos, delta)); \
9563 } \
9564 else \
9565 { \
9566 /* ... otherwise, move i by how much the nearest touched \
9567 point moved. */ \
9568 \
9569 if (position >= original_max_pos) \
9570 delta = sfnt_sub (max_pos, original_max_pos); \
9571 else \
9572 delta = sfnt_sub (min_pos, original_min_pos); \
9573 \
9574 store_point (i, sfnt_add (position, delta)); \
9575 } \
9576 } \
9577
9220/* Interpolate untouched points in the contour between and including 9578/* Interpolate untouched points in the contour between and including
9221 START and END inside INTERPRETER's glyph zone according to the 9579 START and END inside INTERPRETER's glyph zone according to the
9222 rules specified for an IUP instruction. Perform interpolation on 9580 rules specified for an IUP instruction. Perform interpolation on
@@ -9231,25 +9589,10 @@ sfnt_interpret_iup_1 (struct sfnt_interpreter *interpreter,
9231 size_t touch_start, touch_end; 9589 size_t touch_start, touch_end;
9232 size_t first_point; 9590 size_t first_point;
9233 size_t point_min, point_max, i; 9591 size_t point_min, point_max, i;
9234 sfnt_f26dot6 position, min_pos, max_pos, delta; 9592 sfnt_f26dot6 position, min_pos, max_pos, delta, ratio;
9235 sfnt_f26dot6 original_max_pos; 9593 sfnt_f26dot6 original_max_pos;
9236 sfnt_f26dot6 original_min_pos; 9594 sfnt_f26dot6 original_min_pos;
9237 9595
9238#define load_point(p) \
9239 (opcode == 0x31 \
9240 ? interpreter->glyph_zone->x_current[p] \
9241 : interpreter->glyph_zone->x_current[p])
9242
9243#define store_point(p, val) \
9244 (opcode == 0x31 \
9245 ? (interpreter->glyph_zone->x_current[p] = (val)) \
9246 : (interpreter->glyph_zone->y_current[p] = (val)))
9247
9248#define load_original(p) \
9249 (opcode == 0x31 \
9250 ? interpreter->glyph_zone->x_points[p] \
9251 : interpreter->glyph_zone->y_points[p])
9252
9253 /* Find the first touched point. If none is found, simply 9596 /* Find the first touched point. If none is found, simply
9254 return. */ 9597 return. */
9255 9598
@@ -9265,25 +9608,27 @@ sfnt_interpret_iup_1 (struct sfnt_interpreter *interpreter,
9265 9608
9266 point = start; 9609 point = start;
9267 9610
9268 while (true) 9611 /* Find the first touched point. */
9612 while (!(interpreter->glyph_zone->flags[point] & mask))
9269 { 9613 {
9270 /* first_point says when to stop looking for a closing 9614 point++;
9271 point. */
9272 first_point = point;
9273 9615
9616 /* There are no touched points. */
9617 if (point > end)
9618 goto untouched;
9619 }
9620
9621 first_point = point;
9622
9623 while (point <= end)
9624 {
9274 /* Find the next untouched point. */ 9625 /* Find the next untouched point. */
9275 while (interpreter->glyph_zone->flags[point] & mask) 9626 while (interpreter->glyph_zone->flags[point] & mask)
9276 { 9627 {
9277 point++; 9628 point++;
9278 9629
9279 /* Move back to start if point has gone past the end of the
9280 contour. */
9281 if (point > end) 9630 if (point > end)
9282 point = start; 9631 goto wraparound;
9283
9284 if (point == first_point)
9285 /* There are no more untouched points. */
9286 goto untouched;
9287 } 9632 }
9288 9633
9289 /* touch_start is now the first untouched point. */ 9634 /* touch_start is now the first untouched point. */
@@ -9297,94 +9642,31 @@ sfnt_interpret_iup_1 (struct sfnt_interpreter *interpreter,
9297 /* Move back to start if point has gone past the end of the 9642 /* Move back to start if point has gone past the end of the
9298 contour. */ 9643 contour. */
9299 if (point > end) 9644 if (point > end)
9300 point = start; 9645 goto wraparound_1;
9301
9302 if (point == touch_start)
9303 /* There are no more touched points. */
9304 goto untouched;
9305 } 9646 }
9306 9647
9307 /* touch_end is now the next touched point. */ 9648 /* touch_end is now the next touched point. */
9308 touch_end = point; 9649 touch_end = point;
9309 9650
9310 /* Now make touch_start the first point before, i.e. the first 9651 /* Do the interpolation. */
9311 touched point in this pair. */ 9652 IUP_SINGLE_PAIR ();
9312 9653 }
9313 if (touch_start == start)
9314 touch_start = end;
9315 else
9316 touch_start = touch_start - 1;
9317
9318 /* Set point_min and point_max based on which glyph is at a
9319 lower value. */
9320
9321 if (load_original (touch_start) < touch_end)
9322 {
9323 point_min = touch_start;
9324 point_max = touch_end;
9325 }
9326 else
9327 {
9328 point_max = touch_start;
9329 point_min = touch_end;
9330 }
9331
9332 min_pos = load_point (point_min);
9333 max_pos = load_point (point_max);
9334
9335 /* This is needed for interpolation. */
9336 original_max_pos = load_original (max_pos);
9337 original_min_pos = load_original (min_pos);
9338
9339 /* Now process points between touch_start and touch_end. */
9340
9341 i = touch_start;
9342
9343 do
9344 {
9345 ++i;
9346
9347 if (i == end)
9348 i = start;
9349 9654
9350 /* Movement is always relative to the original position of 9655 goto untouched;
9351 the point. */
9352 position = load_original (i);
9353 9656
9354 /* If i is in between touch_start and touch_end... */ 9657 wraparound:
9355 if (position >= original_min_pos 9658 /* This is like wraparound_1, except that no untouched points have
9356 && position <= original_max_pos) 9659 yet to be found.
9357 {
9358 /* ... linearly interpolate i between min_pos and
9359 max_pos... */
9360 delta = sfnt_sub (max_pos, min_pos) / 2;
9361 store_point (i, sfnt_add (max_pos, delta));
9362 }
9363 else
9364 {
9365 /* ... otherwise, move i by how much the nearest touched
9366 point moved. */
9367 9660
9368 if (position >= original_max_pos) 9661 This means the first untouched point is start. */
9369 delta = sfnt_sub (max_pos, original_max_pos); 9662 touch_start = start;
9370 else
9371 delta = sfnt_sub (min_pos, original_min_pos);
9372 9663
9373 store_point (i, position + delta); 9664 wraparound_1:
9374 } 9665 /* If point > end, wrap around. Here, touch_start is set
9375 } 9666 properly, so touch_end must be first_point. */
9376 while (i != touch_end);
9377 9667
9378 /* Handle the degenerate case where the first and last points of 9668 touch_end = first_point;
9379 the entire contour are touched, and as a result the loop 9669 IUP_SINGLE_PAIR ();
9380 continues forever. */
9381 if (touch_start == touch_end)
9382 goto untouched;
9383 }
9384
9385#undef load_point
9386#undef store_point
9387#undef load_original
9388 9670
9389 untouched: 9671 untouched:
9390 /* No points were touched or all points have been considered, so 9672 /* No points were touched or all points have been considered, so
@@ -9392,6 +9674,10 @@ sfnt_interpret_iup_1 (struct sfnt_interpreter *interpreter,
9392 return; 9674 return;
9393} 9675}
9394 9676
9677#undef load_point
9678#undef store_point
9679#undef load_original
9680
9395/* Interpret an IUP (``interpolate untouched points'') instruction. 9681/* Interpret an IUP (``interpolate untouched points'') instruction.
9396 INTERPRETER is the interpreter, and OPCODE is the instruction 9682 INTERPRETER is the interpreter, and OPCODE is the instruction
9397 number. See the TrueType Reference Manual for more details. */ 9683 number. See the TrueType Reference Manual for more details. */
@@ -9412,7 +9698,7 @@ sfnt_interpret_iup (struct sfnt_interpreter *interpreter,
9412 TRAP ("iup without loaded glyph!"); 9698 TRAP ("iup without loaded glyph!");
9413 9699
9414 /* Figure out what axis to interpolate in based on the opcode. */ 9700 /* Figure out what axis to interpolate in based on the opcode. */
9415 if (opcode == 0x31) 9701 if (opcode == 0x30)
9416 mask = SFNT_POINT_TOUCHED_Y; 9702 mask = SFNT_POINT_TOUCHED_Y;
9417 else 9703 else
9418 mask = SFNT_POINT_TOUCHED_X; 9704 mask = SFNT_POINT_TOUCHED_X;
@@ -9435,6 +9721,233 @@ sfnt_interpret_iup (struct sfnt_interpreter *interpreter,
9435 } 9721 }
9436} 9722}
9437 9723
9724/* Interpret an MIRP instruction with the specified OPCODE in
9725 INTERPRETER. Pop a point in ZP1 and CVT index, and move the point
9726 until its distance from RP0 in ZP0 is the same as in the control
9727 value. If the point lies in the twilight zone, then ``create'' it
9728 as well.
9729
9730 OPCODE contains a great many flags.
9731 They are all described in the TrueType reference manual. */
9732
9733static void
9734sfnt_interpret_mirp (struct sfnt_interpreter *interpreter,
9735 uint32_t opcode)
9736{
9737 uint32_t n;
9738 uint32_t p;
9739 sfnt_f26dot6 distance, delta, temp;
9740 sfnt_f26dot6 current_projection, original_projection;
9741 sfnt_f26dot6 x, y, org_x, org_y;
9742 sfnt_f26dot6 rx, ry, org_rx, org_ry;
9743
9744 /* CVT index. */
9745 n = POP ();
9746
9747 /* Point number. */
9748 p = POP ();
9749
9750 /* Now get the distance from the CVT. */
9751 if (n >= interpreter->cvt_size)
9752 TRAP ("cvt index out of bounds");
9753
9754 distance = interpreter->cvt[n];
9755
9756 /* Test against the single width value. */
9757
9758 delta = sfnt_sub (distance,
9759 interpreter->state.single_width_value);
9760
9761 if (delta < 0)
9762 delta = -delta;
9763
9764 if (delta < interpreter->state.sw_cut_in)
9765 {
9766 /* Use the single width instead, as the CVT entry is too
9767 small. */
9768
9769 if (distance >= 0)
9770 distance = interpreter->state.single_width_value;
9771 else
9772 distance = -interpreter->state.single_width_value;
9773 }
9774
9775 /* Load the reference point. */
9776 sfnt_address_zp0 (interpreter, interpreter->state.rp0,
9777 &rx, &ry, &org_rx, &org_ry);
9778
9779 /* Create the point in the twilight zone, should that be ZP1. */
9780
9781 if (!interpreter->state.zp1)
9782 {
9783 /* Since P hasn't been loaded yet, whether or not it is valid is
9784 not known. */
9785 sfnt_check_zp1 (interpreter, p);
9786
9787 interpreter->twilight_x[p] = rx;
9788 interpreter->twilight_y[p] = ry;
9789
9790 temp = sfnt_mul_f2dot14 (interpreter->state.projection_vector.x,
9791 distance);
9792 temp = sfnt_add (temp, org_rx);
9793 interpreter->twilight_original_x[p] = temp;
9794
9795 temp = sfnt_mul_f2dot14 (interpreter->state.projection_vector.y,
9796 distance);
9797 temp = sfnt_add (temp, org_ry);
9798 interpreter->twilight_original_y[p] = temp;
9799 }
9800
9801 /* Load P. */
9802 sfnt_address_zp1 (interpreter, p, &x, &y, &org_x, &org_y);
9803
9804 /* If distance would be negative and auto_flip is on, flip it. */
9805
9806 original_projection = DUAL_PROJECT (org_x - org_rx,
9807 org_y - org_ry);
9808 current_projection = PROJECT (x - rx, y - ry);
9809
9810 if (interpreter->state.auto_flip)
9811 {
9812 if ((original_projection ^ distance) < 0)
9813 distance = -distance;
9814 }
9815
9816 /* Flag B means look at the cvt cut in and round the
9817 distance. */
9818
9819 if (opcode & 4)
9820 {
9821 delta = sfnt_sub (distance, original_projection);
9822
9823 if (delta < 0)
9824 delta = -delta;
9825
9826 if (delta > interpreter->state.cvt_cut_in)
9827 distance = original_projection;
9828
9829 /* Now, round the distance. */
9830 distance = sfnt_round_symmetric (interpreter, distance);
9831 }
9832
9833 /* Flag C means look at the minimum distance. */
9834
9835 if (opcode & 8)
9836 {
9837 if (original_projection >= 0
9838 && distance < interpreter->state.minimum_distance)
9839 distance = interpreter->state.minimum_distance;
9840 else if (original_projection < 0
9841 && distance > -interpreter->state.minimum_distance)
9842 distance = -interpreter->state.minimum_distance;
9843 }
9844
9845 /* Finally, move the point. */
9846 sfnt_move_zp1 (interpreter, p, 1,
9847 sfnt_sub (distance, current_projection));
9848
9849 /* Set RP1 to RP0 and RP2 to the point. If flag 3 is set, also make
9850 it RP0. */
9851 interpreter->state.rp1 = interpreter->state.rp0;
9852 interpreter->state.rp2 = p;
9853
9854 if (opcode & 16)
9855 interpreter->state.rp0 = p;
9856}
9857
9858/* Interpret an MDRP instruction with the specified OPCODE in
9859 INTERPRETER. Pop a point in ZP1, and move the point until its
9860 distance from RP0 in ZP0 is the same as in the original outline.
9861
9862 This is almost like MIRP[abcde].
9863
9864 OPCODE contains a great many flags.
9865 They are all described in the TrueType reference manual. */
9866
9867static void
9868sfnt_interpret_mdrp (struct sfnt_interpreter *interpreter,
9869 uint32_t opcode)
9870{
9871 uint32_t p;
9872 sfnt_f26dot6 distance, delta;
9873 sfnt_f26dot6 current_projection, original_projection;
9874 sfnt_f26dot6 x, y, org_x, org_y;
9875 sfnt_f26dot6 rx, ry, org_rx, org_ry;
9876
9877 /* Point number. */
9878 p = POP ();
9879
9880 /* Load the points. */
9881 sfnt_address_zp1 (interpreter, p, &x, &y, &org_x, &org_y);
9882 sfnt_address_zp0 (interpreter, interpreter->state.rp0,
9883 &rx, &ry, &org_rx, &org_ry);
9884
9885 distance = DUAL_PROJECT (org_x - org_rx,
9886 org_y - org_ry);
9887 original_projection = distance;
9888 current_projection = PROJECT (x - rx, y - ry);
9889
9890 /* Test against the single width value. */
9891
9892 delta = sfnt_sub (distance,
9893 interpreter->state.single_width_value);
9894
9895 if (delta < 0)
9896 delta = -delta;
9897
9898 if (delta < interpreter->state.sw_cut_in)
9899 {
9900 /* Use the single width instead, as the CVT entry is too
9901 small. */
9902
9903 if (distance >= 0)
9904 distance = interpreter->state.single_width_value;
9905 else
9906 distance = -interpreter->state.single_width_value;
9907 }
9908
9909 /* Flag B means look at the cvt cut in and round the
9910 distance. */
9911
9912 if (opcode & 4)
9913 {
9914 delta = sfnt_sub (distance, original_projection);
9915
9916 if (delta < 0)
9917 delta = -delta;
9918
9919 if (delta > interpreter->state.cvt_cut_in)
9920 distance = original_projection;
9921
9922 /* Now, round the distance. */
9923 distance = sfnt_round_symmetric (interpreter, distance);
9924 }
9925
9926 /* Flag C means look at the minimum distance. */
9927
9928 if (opcode & 8)
9929 {
9930 if (original_projection >= 0
9931 && distance < interpreter->state.minimum_distance)
9932 distance = interpreter->state.minimum_distance;
9933 else if (original_projection < 0
9934 && distance > -interpreter->state.minimum_distance)
9935 distance = -interpreter->state.minimum_distance;
9936 }
9937
9938 /* Finally, move the point. */
9939 sfnt_move_zp1 (interpreter, p, 1,
9940 sfnt_sub (distance, current_projection));
9941
9942 /* Set RP1 to RP0 and RP2 to the point. If flag 3 is set, also make
9943 it RP0. */
9944 interpreter->state.rp1 = interpreter->state.rp0;
9945 interpreter->state.rp2 = p;
9946
9947 if (opcode & 16)
9948 interpreter->state.rp0 = p;
9949}
9950
9438/* Execute the program now loaded into INTERPRETER. 9951/* Execute the program now loaded into INTERPRETER.
9439 WHY specifies why the interpreter is being run, and is used to 9952 WHY specifies why the interpreter is being run, and is used to
9440 control the behavior of instructions such IDEF[] and FDEF[]. 9953 control the behavior of instructions such IDEF[] and FDEF[].
@@ -9466,6 +9979,11 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
9466 { 9979 {
9467 opcode = interpreter->instructions[interpreter->IP]; 9980 opcode = interpreter->instructions[interpreter->IP];
9468 9981
9982#ifdef TEST
9983 if (interpreter->run_hook)
9984 interpreter->run_hook (interpreter);
9985#endif
9986
9469 switch (opcode) 9987 switch (opcode)
9470 { 9988 {
9471 case 0x00: /* SVTCA y */ 9989 case 0x00: /* SVTCA y */
@@ -9930,19 +10448,19 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
9930 break; 10448 break;
9931 10449
9932 case 0x80: /* FLIPPT */ 10450 case 0x80: /* FLIPPT */
9933 NOT_IMPLEMENTED (); 10451 FLIPPT ();
9934 break; 10452 break;
9935 10453
9936 case 0x81: /* FLIPRGON */ 10454 case 0x81: /* FLIPRGON */
9937 NOT_IMPLEMENTED (); 10455 FLIPRGON ();
9938 break; 10456 break;
9939 10457
9940 case 0x82: /* FLIPRGOFF */ 10458 case 0x82: /* FLIPRGOFF */
9941 NOT_IMPLEMENTED (); 10459 FLIPRGOFF ();
9942 break; 10460 break;
9943 10461
9944 case 0x83: /* UNKNOWN */ 10462 case 0x83: /* RMVT */
9945 case 0x84: /* UNKNOWN */ 10463 case 0x84: /* WMVT */
9946 NOT_IMPLEMENTED (); 10464 NOT_IMPLEMENTED ();
9947 break; 10465 break;
9948 10466
@@ -9950,9 +10468,9 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
9950 SCANCTRL (); 10468 SCANCTRL ();
9951 break; 10469 break;
9952 10470
9953 case 0x86: /* SDPvTL */ 10471 case 0x86: /* SDPVTL */
9954 case 0x87: /* SDPvTL */ 10472 case 0x87: /* SDPVTL */
9955 NOT_IMPLEMENTED (); 10473 SDPVTL ();
9956 break; 10474 break;
9957 10475
9958 case 0x88: /* GETINFO */ 10476 case 0x88: /* GETINFO */
@@ -9993,9 +10511,13 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter,
9993 10511
9994 default: 10512 default:
9995 if (opcode >= 0xE0) /* MIRP */ 10513 if (opcode >= 0xE0) /* MIRP */
9996 NOT_IMPLEMENTED (); 10514 {
10515 MIRP ();
10516 }
9997 else if (opcode >= 0xC0) /* MDRP */ 10517 else if (opcode >= 0xC0) /* MDRP */
9998 NOT_IMPLEMENTED (); 10518 {
10519 MDRP ();
10520 }
9999 else if (opcode >= 0xB8) /* PUSHW */ 10521 else if (opcode >= 0xB8) /* PUSHW */
10000 { 10522 {
10001 PUSHW (); 10523 PUSHW ();
@@ -10094,7 +10616,7 @@ sfnt_interpret_control_value_program (struct sfnt_interpreter *interpreter,
10094 10616
10095/* Structure describing a single scaled and fitted outline. */ 10617/* Structure describing a single scaled and fitted outline. */
10096 10618
10097struct sfnt_scaled_outline 10619struct sfnt_instructed_outline
10098{ 10620{
10099 /* The number of points in this contour, including the two phantom 10621 /* The number of points in this contour, including the two phantom
10100 points at the end. */ 10622 points at the end. */
@@ -10109,10 +10631,217 @@ struct sfnt_scaled_outline
10109 /* The points of each contour, with two additional phantom points at 10631 /* The points of each contour, with two additional phantom points at
10110 the end. */ 10632 the end. */
10111 sfnt_f26dot6 *restrict x_points, *restrict y_points; 10633 sfnt_f26dot6 *restrict x_points, *restrict y_points;
10634
10635 /* The flags of each point. */
10636 unsigned char *flags;
10112}; 10637};
10113 10638
10114 10639
10115 10640
10641/* Instructed glyph outline decomposition. This is separate from
10642 sfnt_decompose_glyph because this file should be able to be built
10643 with instructions disabled. */
10644
10645/* Decompose OUTLINE, an instructed outline, into its individual
10646 components.
10647
10648 Call MOVE_TO to move to a specific location. For each line
10649 encountered, call LINE_TO to draw a line to that location. For
10650 each spline encountered, call CURVE_TO to draw the curves
10651 comprising the spline. Call each of those functions with 16.16
10652 fixed point coordinates.
10653
10654 All functions will be called with DCONTEXT as an argument.
10655
10656 The winding rule used to fill the resulting lines is described in
10657 chapter 2 of the TrueType reference manual, under the heading
10658 "distinguishing the inside from the outside of a glyph."
10659
10660 Value is 0 upon success, or some non-zero value upon failure, which
10661 can happen if the glyph is invalid. */
10662
10663static int
10664sfnt_decompose_instructed_outline (struct sfnt_instructed_outline *outline,
10665 sfnt_move_to_proc move_to,
10666 sfnt_line_to_proc line_to,
10667 sfnt_curve_to_proc curve_to,
10668 void *dcontext)
10669{
10670 size_t here, start, last;
10671 struct sfnt_point pen, control1, control2;
10672 size_t n;
10673
10674 if (!outline->num_contours)
10675 return 0;
10676
10677 here = 0;
10678
10679 for (n = 0; n < outline->num_contours; ++n)
10680 {
10681 /* here is the first index into the glyph's point arrays
10682 belonging to the contour in question. last is the index
10683 of the last point in the contour. */
10684 last = outline->contour_end_points[n];
10685
10686 /* Move to the start. */
10687 pen.x = outline->x_points[here] * 1024;
10688 pen.y = outline->y_points[here] * 1024;
10689 move_to (pen, dcontext);
10690
10691 /* Record start so the contour can be closed. */
10692 start = here;
10693
10694 /* If there is only one point in a contour, draw a one pixel
10695 wide line. */
10696 if (last == here)
10697 {
10698 line_to (pen, dcontext);
10699 here++;
10700
10701 continue;
10702 }
10703
10704 if (here > last)
10705 /* Indices moved backwards. */
10706 goto fail;
10707
10708 /* Now start reading points. If the next point is on the
10709 curve, then it is actually a line. */
10710 for (++here; here <= last; ++here)
10711 {
10712 /* Make sure here is within bounds. */
10713 if (here >= outline->num_points)
10714 return 1;
10715
10716 if (outline->flags[here] & 01) /* On Curve */
10717 {
10718 pen.x = outline->x_points[here] * 1024;
10719 pen.y = outline->y_points[here] * 1024;
10720
10721 /* See if the last point was on the curve. If it
10722 wasn't, then curve from there to here. */
10723 if (!(outline->flags[here - 1] & 01))
10724 {
10725 control1.x = outline->x_points[here - 1] * 1024;
10726 control1.y = outline->y_points[here - 1] * 1024;
10727 curve_to (control1, pen, dcontext);
10728 }
10729 else
10730 /* Otherwise, this is an ordinary line from there
10731 to here. */
10732 line_to (pen, dcontext);
10733
10734 continue;
10735 }
10736
10737 /* If the last point was on the curve, then there's
10738 nothing extraordinary to do yet. */
10739 if (outline->flags[here - 1] & 01)
10740 ;
10741 else
10742 {
10743 /* Otherwise, interpolate the point halfway between
10744 the last and current points and make that point
10745 the pen. */
10746 control1.x = outline->x_points[here - 1] * 1024;
10747 control1.y = outline->y_points[here - 1] * 1024;
10748 control2.x = outline->x_points[here] * 1024;
10749 control2.y = outline->y_points[here] * 1024;
10750 sfnt_lerp_half (&control1, &control2, &pen);
10751 curve_to (control1, pen, dcontext);
10752 }
10753 }
10754
10755 /* Now close the contour if there is more than one point
10756 inside it. */
10757 if (start != here - 1)
10758 {
10759 /* Restore here after the for loop increased it. */
10760 here --;
10761
10762 if (outline->flags[start] & 01) /* On Curve */
10763 {
10764 pen.x = outline->x_points[start] * 1024;
10765 pen.y = outline->y_points[start] * 1024;
10766
10767 /* See if the last point (in this case, `here') was
10768 on the curve. If it wasn't, then curve from
10769 there to here. */
10770 if (!(outline->flags[here] & 01))
10771 {
10772 control1.x = outline->x_points[here] * 1024;
10773 control1.y = outline->y_points[here] * 1024;
10774 curve_to (control1, pen, dcontext);
10775 }
10776 else
10777 /* Otherwise, this is an ordinary line from there
10778 to here. */
10779 line_to (pen, dcontext);
10780 }
10781
10782 /* Restore here to where it was earlier. */
10783 here++;
10784 }
10785 }
10786
10787 return 0;
10788
10789 fail:
10790 return 1;
10791}
10792
10793/* Decompose and build an outline for the specified instructed outline
10794 INSTRUCTED. Return the outline data with a refcount of 0 upon
10795 success, or NULL upon failure.
10796
10797 This function is not reentrant. */
10798
10799static struct sfnt_glyph_outline *
10800sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed)
10801{
10802 struct sfnt_glyph_outline *outline;
10803 int rc;
10804
10805 /* Allocate the outline now with enough for 44 words at the end. */
10806 outline = xmalloc (sizeof *outline + 40 * sizeof (*outline->outline));
10807 outline->outline_size = 40;
10808 outline->outline_used = 0;
10809 outline->refcount = 0;
10810 outline->outline
10811 = (struct sfnt_glyph_outline_command *) (outline + 1);
10812
10813 /* Clear outline bounding box. */
10814 outline->xmin = 0;
10815 outline->ymin = 0;
10816 outline->xmax = 0;
10817 outline->ymax = 0;
10818
10819 /* Set up the context. */
10820 build_outline_context.outline = outline;
10821 build_outline_context.factor = 0177777;
10822
10823 /* Start decomposing. */
10824 rc = sfnt_decompose_instructed_outline (instructed,
10825 sfnt_move_to_and_build,
10826 sfnt_line_to_and_build,
10827 sfnt_curve_to_and_build,
10828 NULL);
10829
10830 /* Synchronize the outline object with what might have changed
10831 inside sfnt_decompose_glyph. */
10832 outline = build_outline_context.outline;
10833
10834 if (rc)
10835 {
10836 xfree (outline);
10837 return NULL;
10838 }
10839
10840 return outline;
10841}
10842
10843
10844
10116/* Compute phantom points for the specified glyph GLYPH. Use the 10845/* Compute phantom points for the specified glyph GLYPH. Use the
10117 unscaled metrics specified in METRICS, and the 16.16 fixed point 10846 unscaled metrics specified in METRICS, and the 16.16 fixed point
10118 scale SCALE. 10847 scale SCALE.
@@ -10134,7 +10863,7 @@ sfnt_compute_phantom_points (struct sfnt_glyph *glyph,
10134 represents the left-side bearing distance from xmin, while the 10863 represents the left-side bearing distance from xmin, while the
10135 other represents the advance width. Both are then used after the 10864 other represents the advance width. Both are then used after the
10136 hinting process to ensure that the reported glyph metrics are 10865 hinting process to ensure that the reported glyph metrics are
10137 consistent with the hinted outline. */ 10866 consistent with the instructed outline. */
10138 10867
10139 /* First compute both values in fwords. */ 10868 /* First compute both values in fwords. */
10140 f1 = glyph->xmin - metrics->lbearing; 10869 f1 = glyph->xmin - metrics->lbearing;
@@ -10160,33 +10889,28 @@ static const char *
10160sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph, 10889sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
10161 struct sfnt_interpreter *interpreter, 10890 struct sfnt_interpreter *interpreter,
10162 struct sfnt_glyph_metrics *metrics, 10891 struct sfnt_glyph_metrics *metrics,
10163 struct sfnt_scaled_outline **value) 10892 struct sfnt_instructed_outline **value)
10164{ 10893{
10165 size_t zone_size, temp, outline_size, i; 10894 size_t zone_size, temp, outline_size, i;
10166 struct sfnt_interpreter_zone *zone; 10895 struct sfnt_interpreter_zone *volatile zone;
10167 sfnt_f26dot6 phantom_point_1_x; 10896 sfnt_f26dot6 phantom_point_1_x;
10168 sfnt_f26dot6 phantom_point_1_y; 10897 sfnt_f26dot6 phantom_point_1_y;
10169 sfnt_f26dot6 phantom_point_2_x; 10898 sfnt_f26dot6 phantom_point_2_x;
10170 sfnt_f26dot6 phantom_point_2_y; 10899 sfnt_f26dot6 phantom_point_2_y;
10171 sfnt_f26dot6 tem; 10900 sfnt_f26dot6 tem;
10172 bool zone_was_allocated; 10901 volatile bool zone_was_allocated;
10173 struct sfnt_scaled_outline *outline; 10902 struct sfnt_instructed_outline *outline;
10174 10903
10175 zone_size = 0; 10904 zone_size = 0;
10176 zone_was_allocated = false; 10905 zone_was_allocated = false;
10177 10906
10178 /* Calculate the size of the zone structure. 10907 /* Calculate the size of the zone structure. */
10179
10180 This should include four longs for each point (including two
10181 phantom points at the end), and then one size_t and one char for
10182 each point, once again including the phantom points, and finally
10183 the size of the zone structure. */
10184 10908
10185 if (INT_MULTIPLY_WRAPV (glyph->simple->number_of_points + 2, 10909 if (INT_MULTIPLY_WRAPV (glyph->simple->number_of_points + 2,
10186 sizeof *zone->x_points * 4, 10910 sizeof *zone->x_points * 4,
10187 &temp) 10911 &temp)
10188 || INT_ADD_WRAPV (temp, zone_size, &zone_size) 10912 || INT_ADD_WRAPV (temp, zone_size, &zone_size)
10189 || INT_MULTIPLY_WRAPV (glyph->simple->number_of_points + 2, 10913 || INT_MULTIPLY_WRAPV (glyph->number_of_contours,
10190 sizeof *zone->contour_end_points, 10914 sizeof *zone->contour_end_points,
10191 &temp) 10915 &temp)
10192 || INT_ADD_WRAPV (temp, zone_size, &zone_size) 10916 || INT_ADD_WRAPV (temp, zone_size, &zone_size)
@@ -10194,7 +10918,7 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
10194 sizeof *zone->flags, 10918 sizeof *zone->flags,
10195 &temp) 10919 &temp)
10196 || INT_ADD_WRAPV (temp, zone_size, &zone_size) 10920 || INT_ADD_WRAPV (temp, zone_size, &zone_size)
10197 || INT_ADD_WRAPV (sizeof (*zone), zone_size, &zone_size)) 10921 || INT_ADD_WRAPV (sizeof *zone, zone_size, &zone_size))
10198 return "Glyph exceeded maximum permissible size"; 10922 return "Glyph exceeded maximum permissible size";
10199 10923
10200 /* Don't use malloc if possible. */ 10924 /* Don't use malloc if possible. */
@@ -10210,9 +10934,9 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
10210 /* Now load the zone with data. */ 10934 /* Now load the zone with data. */
10211 zone->num_points = glyph->simple->number_of_points + 2; 10935 zone->num_points = glyph->simple->number_of_points + 2;
10212 zone->num_contours = glyph->number_of_contours; 10936 zone->num_contours = glyph->number_of_contours;
10213 zone->contour_end_points = (size_t *) (glyph + 1); 10937 zone->contour_end_points = (size_t *) (zone + 1);
10214 zone->x_points = (sfnt_f26dot6 *) (zone->contour_end_points 10938 zone->x_points = (sfnt_f26dot6 *) (zone->contour_end_points
10215 + zone->num_points); 10939 + zone->num_contours);
10216 zone->x_current = zone->x_points + zone->num_points; 10940 zone->x_current = zone->x_points + zone->num_points;
10217 zone->y_points = zone->x_current + zone->num_points; 10941 zone->y_points = zone->x_current + zone->num_points;
10218 zone->y_current = zone->y_points + zone->num_points; 10942 zone->y_current = zone->y_points + zone->num_points;
@@ -10268,6 +10992,10 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
10268 zone->y_current[i] = phantom_point_1_x; 10992 zone->y_current[i] = phantom_point_1_x;
10269 zone->y_current[i + 1] = phantom_point_2_x; 10993 zone->y_current[i + 1] = phantom_point_2_x;
10270 10994
10995 /* Load phantom point flags. */
10996 zone->flags[i] = 0;
10997 zone->flags[i + 1] = 0;
10998
10271 /* Load contour end points. */ 10999 /* Load contour end points. */
10272 for (i = 0; i < zone->num_contours; ++i) 11000 for (i = 0; i < zone->num_contours; ++i)
10273 zone->contour_end_points[i] 11001 zone->contour_end_points[i]
@@ -10298,6 +11026,7 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
10298 * sizeof *outline->contour_end_points); 11026 * sizeof *outline->contour_end_points);
10299 outline_size += (zone->num_points 11027 outline_size += (zone->num_points
10300 * sizeof *outline->x_points * 2); 11028 * sizeof *outline->x_points * 2);
11029 outline_size += zone->num_points;
10301 11030
10302 /* Allocate the outline. */ 11031 /* Allocate the outline. */
10303 outline = xmalloc (outline_size); 11032 outline = xmalloc (outline_size);
@@ -10307,14 +11036,17 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
10307 outline->x_points = (sfnt_f26dot6 *) (outline->contour_end_points 11036 outline->x_points = (sfnt_f26dot6 *) (outline->contour_end_points
10308 + outline->num_contours); 11037 + outline->num_contours);
10309 outline->y_points = outline->x_points + outline->num_points; 11038 outline->y_points = outline->x_points + outline->num_points;
11039 outline->flags = (unsigned char *) (outline->y_points
11040 + outline->num_points);
10310 11041
10311 /* Copy over the contour endpoints and points. */ 11042 /* Copy over the contour endpoints, points, and flags. */
10312 memcpy (outline->contour_end_points, zone->contour_end_points, 11043 memcpy (outline->contour_end_points, zone->contour_end_points,
10313 zone->num_contours * sizeof *outline->contour_end_points); 11044 zone->num_contours * sizeof *outline->contour_end_points);
10314 memcpy (outline->x_points, zone->x_current, 11045 memcpy (outline->x_points, zone->x_current,
10315 zone->num_points * sizeof *outline->x_points); 11046 zone->num_points * sizeof *outline->x_points);
10316 memcpy (outline->y_points, zone->y_current, 11047 memcpy (outline->y_points, zone->y_current,
10317 zone->num_points * sizeof *outline->y_points); 11048 zone->num_points * sizeof *outline->y_points);
11049 memcpy (outline->flags, zone->flags, zone->num_points);
10318 11050
10319 /* Free the zone if necessary. */ 11051 /* Free the zone if necessary. */
10320 if (zone_was_allocated) 11052 if (zone_was_allocated)
@@ -13171,18 +13903,18 @@ static struct sfnt_interpreter_test all_tests[] =
13171 }, 13903 },
13172 { 13904 {
13173 "IDEF", 13905 "IDEF",
13174 /* PUSHB[0] 247 13906 /* PUSHB[0] 0x83
13175 IDEF[] 13907 IDEF[]
13176 PUSHB[3] 1 2 3 4 13908 PUSHB[3] 1 2 3 4
13177 POP[] 13909 POP[]
13178 ENDF[] 13910 ENDF[]
13179 247 */ 13911 0x83 */
13180 (unsigned char []) { 0xb0, 247, 13912 (unsigned char []) { 0xb0, 0x83,
13181 0x89, 13913 0x89,
13182 0xb3, 1, 2, 3, 4, 13914 0xb3, 1, 2, 3, 4,
13183 0x21, 13915 0x21,
13184 0x2d, 13916 0x2d,
13185 247, }, 13917 0x83, },
13186 11, 13918 11,
13187 &idef_test_args, 13919 &idef_test_args,
13188 sfnt_generic_check, 13920 sfnt_generic_check,
@@ -13259,6 +13991,464 @@ static struct sfnt_interpreter_test all_tests[] =
13259 13991
13260 13992
13261 13993
13994/* Instruction debugger. */
13995
13996/* The debugger's X display. */
13997static Display *display;
13998
13999/* The debugger window. */
14000static Window window;
14001
14002/* The GC. */
14003static GC point_gc, background_gc;
14004
14005static void
14006sfnt_setup_debugger (void)
14007{
14008 XGCValues gcv;
14009 Font font;
14010
14011 display = XOpenDisplay (NULL);
14012
14013 if (!display)
14014 exit (1);
14015
14016 window = XCreateSimpleWindow (display, DefaultRootWindow (display),
14017 0, 0, 200, 200, 0, 0,
14018 WhitePixel (display,
14019 DefaultScreen (display)));
14020 XMapWindow (display, window);
14021
14022 /* Select for the appropriate events. */
14023 XSelectInput (display, window, KeyPressMask | ExposureMask);
14024
14025 /* Find an appropriate font. */
14026 font = XLoadFont (display, "6x13");
14027
14028 if (!font)
14029 exit (1);
14030
14031 /* The debugger has been set up. Set up the GCs for drawing points
14032 and backgrounds. */
14033
14034 gcv.foreground = BlackPixel (display, DefaultScreen (display));
14035 gcv.font = font;
14036 point_gc = XCreateGC (display, window, GCForeground | GCFont,
14037 &gcv);
14038 gcv.foreground = WhitePixel (display, DefaultScreen (display));
14039 background_gc = XCreateGC (display, window, GCForeground, &gcv);
14040}
14041
14042static const char *
14043sfnt_name_instruction (unsigned char opcode)
14044{
14045 static const char *const opcode_names[256] = {
14046 "7 SVTCA y",
14047 "7 SVTCA x",
14048 "8 SPvTCA y",
14049 "8 SPvTCA x",
14050 "8 SFvTCA y",
14051 "8 SFvTCA x",
14052 "8 SPvTL ||",
14053 "7 SPvTL +",
14054 "8 SFvTL ||",
14055 "7 SFvTL +",
14056 "5 SPvFS",
14057 "5 SFvFS",
14058 "3 GPv",
14059 "3 GFv",
14060 "6 SFvTPv",
14061 "5 ISECT",
14062
14063 "4 SRP0",
14064 "4 SRP1",
14065 "4 SRP2",
14066 "4 SZP0",
14067 "4 SZP1",
14068 "4 SZP2",
14069 "4 SZPS",
14070 "5 SLOOP",
14071 "3 RTG",
14072 "4 RTHG",
14073 "3 SMD",
14074 "4 ELSE",
14075 "4 JMPR",
14076 "6 SCvTCi",
14077 "5 SSwCi",
14078 "3 SSW",
14079
14080 "3 DUP",
14081 "3 POP",
14082 "5 CLEAR",
14083 "4 SWAP",
14084 "5 DEPTH",
14085 "6 CINDEX",
14086 "6 MINDEX",
14087 "8 AlignPTS",
14088 "7 INS_$28",
14089 "3 UTP",
14090 "8 LOOPCALL",
14091 "4 CALL",
14092 "4 FDEF",
14093 "4 ENDF",
14094 "7 MDAP[0]",
14095 "7 MDAP[1]",
14096
14097 "6 IUP[0]",
14098 "6 IUP[1]",
14099 "6 SHP[0]",
14100 "6 SHP[1]",
14101 "6 SHC[0]",
14102 "6 SHC[1]",
14103 "6 SHZ[0]",
14104 "6 SHZ[1]",
14105 "5 SHPIX",
14106 "2 IP",
14107 "8 MSIRP[0]",
14108 "8 MSIRP[1]",
14109 "7 AlignRP",
14110 "4 RTDG",
14111 "7 MIAP[0]",
14112 "7 MIAP[1]",
14113
14114 "6 NPushB",
14115 "6 NPushW",
14116 "2 WS",
14117 "2 RS",
14118 "5 WCvtP",
14119 "4 RCvt",
14120 "5 GC[0]",
14121 "5 GC[1]",
14122 "4 SCFS",
14123 "5 MD[0]",
14124 "5 MD[1]",
14125 "5 MPPEM",
14126 "3 MPS",
14127 "6 FlipON",
14128 "7 FlipOFF",
14129 "5 DEBUG",
14130
14131 "2 LT",
14132 "4 LTEQ",
14133 "2 GT",
14134 "4 GTEQ",
14135 "2 EQ",
14136 "3 NEQ",
14137 "3 ODD",
14138 "4 EVEN",
14139 "2 IF",
14140 "3 EIF",
14141 "3 AND",
14142 "2 OR",
14143 "3 NOT",
14144 "7 DeltaP1",
14145 "3 SDB",
14146 "3 SDS",
14147
14148 "3 ADD",
14149 "3 SUB",
14150 "3 DIV",
14151 "3 MUL",
14152 "3 ABS",
14153 "3 NEG",
14154 "5 FLOOR",
14155 "7 CEILING",
14156 "8 ROUND[0]",
14157 "8 ROUND[1]",
14158 "8 ROUND[2]",
14159 "8 ROUND[3]",
14160 "9 NROUND[0]",
14161 "9 NROUND[1]",
14162 "9 NROUND[2]",
14163 "9 NROUND[3]",
14164
14165 "5 WCvtF",
14166 "7 DeltaP2",
14167 "7 DeltaP3",
14168 "A DeltaCn[0]",
14169 "A DeltaCn[1]",
14170 "A DeltaCn[2]",
14171 "6 SROUND",
14172 "8 S45Round",
14173 "4 JROT",
14174 "4 JROF",
14175 "4 ROFF",
14176 "7 INS_$7B",
14177 "4 RUTG",
14178 "4 RDTG",
14179 "5 SANGW",
14180 "2 AA",
14181
14182 "6 FlipPT",
14183 "8 FlipRgON",
14184 "9 FlipRgOFF",
14185 "7 INS_$83",
14186 "7 INS_$84",
14187 "8 ScanCTRL",
14188 "9 SDPvTL[0]",
14189 "9 SDPvTL[1]",
14190 "7 GetINFO",
14191 "4 IDEF",
14192 "4 ROLL",
14193 "3 MAX",
14194 "3 MIN",
14195 "8 ScanTYPE",
14196 "8 InstCTRL",
14197 "7 INS_$8F",
14198
14199 "7 INS_$90",
14200#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
14201 "6 GETVAR",
14202 "7 GETDATA",
14203#else
14204 "7 INS_$91",
14205 "7 INS_$92",
14206#endif
14207 "7 INS_$93",
14208 "7 INS_$94",
14209 "7 INS_$95",
14210 "7 INS_$96",
14211 "7 INS_$97",
14212 "7 INS_$98",
14213 "7 INS_$99",
14214 "7 INS_$9A",
14215 "7 INS_$9B",
14216 "7 INS_$9C",
14217 "7 INS_$9D",
14218 "7 INS_$9E",
14219 "7 INS_$9F",
14220
14221 "7 INS_$A0",
14222 "7 INS_$A1",
14223 "7 INS_$A2",
14224 "7 INS_$A3",
14225 "7 INS_$A4",
14226 "7 INS_$A5",
14227 "7 INS_$A6",
14228 "7 INS_$A7",
14229 "7 INS_$A8",
14230 "7 INS_$A9",
14231 "7 INS_$AA",
14232 "7 INS_$AB",
14233 "7 INS_$AC",
14234 "7 INS_$AD",
14235 "7 INS_$AE",
14236 "7 INS_$AF",
14237
14238 "8 PushB[0]",
14239 "8 PushB[1]",
14240 "8 PushB[2]",
14241 "8 PushB[3]",
14242 "8 PushB[4]",
14243 "8 PushB[5]",
14244 "8 PushB[6]",
14245 "8 PushB[7]",
14246 "8 PushW[0]",
14247 "8 PushW[1]",
14248 "8 PushW[2]",
14249 "8 PushW[3]",
14250 "8 PushW[4]",
14251 "8 PushW[5]",
14252 "8 PushW[6]",
14253 "8 PushW[7]",
14254
14255 "7 MDRP[G]",
14256 "7 MDRP[B]",
14257 "7 MDRP[W]",
14258 "7 MDRP[?]",
14259 "8 MDRP[rG]",
14260 "8 MDRP[rB]",
14261 "8 MDRP[rW]",
14262 "8 MDRP[r?]",
14263 "8 MDRP[mG]",
14264 "8 MDRP[mB]",
14265 "8 MDRP[mW]",
14266 "8 MDRP[m?]",
14267 "9 MDRP[mrG]",
14268 "9 MDRP[mrB]",
14269 "9 MDRP[mrW]",
14270 "9 MDRP[mr?]",
14271
14272 "8 MDRP[pG]",
14273 "8 MDRP[pB]",
14274 "8 MDRP[pW]",
14275 "8 MDRP[p?]",
14276 "9 MDRP[prG]",
14277 "9 MDRP[prB]",
14278 "9 MDRP[prW]",
14279 "9 MDRP[pr?]",
14280 "9 MDRP[pmG]",
14281 "9 MDRP[pmB]",
14282 "9 MDRP[pmW]",
14283 "9 MDRP[pm?]",
14284 "A MDRP[pmrG]",
14285 "A MDRP[pmrB]",
14286 "A MDRP[pmrW]",
14287 "A MDRP[pmr?]",
14288
14289 "7 MIRP[G]",
14290 "7 MIRP[B]",
14291 "7 MIRP[W]",
14292 "7 MIRP[?]",
14293 "8 MIRP[rG]",
14294 "8 MIRP[rB]",
14295 "8 MIRP[rW]",
14296 "8 MIRP[r?]",
14297 "8 MIRP[mG]",
14298 "8 MIRP[mB]",
14299 "8 MIRP[mW]",
14300 "8 MIRP[m?]",
14301 "9 MIRP[mrG]",
14302 "9 MIRP[mrB]",
14303 "9 MIRP[mrW]",
14304 "9 MIRP[mr?]",
14305
14306 "8 MIRP[pG]",
14307 "8 MIRP[pB]",
14308 "8 MIRP[pW]",
14309 "8 MIRP[p?]",
14310 "9 MIRP[prG]",
14311 "9 MIRP[prB]",
14312 "9 MIRP[prW]",
14313 "9 MIRP[pr?]",
14314 "9 MIRP[pmG]",
14315 "9 MIRP[pmB]",
14316 "9 MIRP[pmW]",
14317 "9 MIRP[pm?]",
14318 "A MIRP[pmrG]",
14319 "A MIRP[pmrB]",
14320 "A MIRP[pmrW]",
14321 "A MIRP[pmr?]"
14322 };
14323
14324 return opcode_names[opcode];
14325}
14326
14327static void
14328sfnt_draw_debugger (struct sfnt_interpreter *interpreter)
14329{
14330 int x, y, i;
14331 char buffer[80];
14332 const char *name;
14333 int opcode;
14334
14335 sprintf (buffer, "opcode:IP:depth: 0x%x:%d:%d",
14336 interpreter->instructions[interpreter->IP],
14337 interpreter->IP,
14338 interpreter->call_depth);
14339
14340 /* Clear the window. */
14341 XFillRectangle (display, window, background_gc,
14342 0, 0, 65535, 65535);
14343
14344 /* Draw some information about the opcode. */
14345 XDrawString (display, window, point_gc, 0, 13, buffer,
14346 strlen (buffer));
14347
14348 opcode = interpreter->instructions[interpreter->IP];
14349
14350 sprintf (buffer, "opcode: %s",
14351 sfnt_name_instruction (opcode));
14352
14353 XDrawString (display, window, point_gc, 14, 27, buffer,
14354 strlen (buffer));
14355
14356 if (interpreter->state.project
14357 == sfnt_project_onto_x_axis_vector)
14358 name = "X axis";
14359 else if (interpreter->state.project
14360 == sfnt_project_onto_y_axis_vector)
14361 name = "Y axis";
14362 else
14363 name = "Any";
14364
14365 sprintf (buffer, "projection function: %s", name);
14366
14367 XDrawString (display, window, point_gc, 28, 42, buffer,
14368 strlen (buffer));
14369
14370 /* Draw each point onto the window. */
14371 for (i = 0; i < interpreter->glyph_zone->num_points; ++i)
14372 {
14373 x = interpreter->glyph_zone->x_current[i] / 16;
14374 y = (200 - interpreter->glyph_zone->y_current[i] / 16);
14375
14376 XFillRectangle (display, window, point_gc, x, y, 4, 4);
14377 }
14378}
14379
14380static void
14381sfnt_run_hook (struct sfnt_interpreter *interpreter)
14382{
14383 pid_t pid;
14384 XEvent event;
14385
14386 pid = fork ();
14387
14388 if (pid == 0)
14389 {
14390 sfnt_setup_debugger ();
14391
14392 while (true)
14393 {
14394 XNextEvent (display, &event);
14395
14396 switch (event.type)
14397 {
14398 case KeyPress:
14399 XDestroyWindow (display, window);
14400 XCloseDisplay (display);
14401 exit (0);
14402 break;
14403
14404 case Expose:
14405 sfnt_draw_debugger (interpreter);
14406 break;
14407 }
14408 }
14409 }
14410 else
14411 {
14412 while (waitpid (pid, NULL, 0) != pid && errno == EINTR)
14413 /* Spin. */;
14414 }
14415}
14416
14417static void
14418sfnt_verbose (struct sfnt_interpreter *interpreter)
14419{
14420 struct sfnt_instructed_outline temp;
14421 struct sfnt_glyph_outline *outline;
14422 struct sfnt_raster *raster;
14423 unsigned char opcode;
14424
14425 /* Build a temporary outline containing the values of the
14426 interpreter's glyph zone. */
14427 temp.num_points = interpreter->glyph_zone->num_points;
14428 temp.num_contours = interpreter->glyph_zone->num_contours;
14429 temp.contour_end_points = interpreter->glyph_zone->contour_end_points;
14430 temp.x_points = interpreter->glyph_zone->x_current;
14431 temp.y_points = interpreter->glyph_zone->y_current;
14432 temp.flags = interpreter->glyph_zone->flags;
14433 outline = sfnt_build_instructed_outline (&temp);
14434
14435 if (!outline)
14436 return;
14437
14438 raster = sfnt_raster_glyph_outline (outline);
14439
14440 if (raster)
14441 sfnt_test_raster (raster);
14442
14443 xfree (outline);
14444 xfree (raster);
14445
14446 opcode = interpreter->instructions[interpreter->IP];
14447 printf ("opcode: %s\n", sfnt_name_instruction (opcode));
14448}
14449
14450
14451
13262/* Main entry point. */ 14452/* Main entry point. */
13263 14453
13264/* Simple tests that were used while developing this file. By the 14454/* Simple tests that were used while developing this file. By the
@@ -13283,7 +14473,7 @@ static struct sfnt_interpreter_test all_tests[] =
13283 -Wno-missing-field-initializers -Wno-override-init 14473 -Wno-missing-field-initializers -Wno-override-init
13284 -Wno-sign-compare -Wno-type-limits -Wno-unused-parameter 14474 -Wno-sign-compare -Wno-type-limits -Wno-unused-parameter
13285 -Wno-format-nonliteral -Wno-bidi-chars -g3 -O0 -DTEST sfnt.c -o 14475 -Wno-format-nonliteral -Wno-bidi-chars -g3 -O0 -DTEST sfnt.c -o
13286 sfnt ../lib/libgnu.a 14476 sfnt ../lib/libgnu.a -lX11
13287 14477
13288 after gnulib has been built. Then, run ./sfnt 14478 after gnulib has been built. Then, run ./sfnt
13289 /path/to/font.ttf. */ 14479 /path/to/font.ttf. */
@@ -13322,6 +14512,7 @@ main (int argc, char **argv)
13322 const char *trap; 14512 const char *trap;
13323 struct sfnt_prep_table *prep; 14513 struct sfnt_prep_table *prep;
13324 struct sfnt_graphics_state state; 14514 struct sfnt_graphics_state state;
14515 struct sfnt_instructed_outline *value;
13325 14516
13326 if (argc != 2) 14517 if (argc != 2)
13327 return 1; 14518 return 1;
@@ -13439,7 +14630,8 @@ main (int argc, char **argv)
13439 cvt ? cvt->num_elements : 0ul); 14630 cvt ? cvt->num_elements : 0ul);
13440 14631
13441 interpreter = sfnt_make_interpreter (maxp, cvt, head, 14632 interpreter = sfnt_make_interpreter (maxp, cvt, head,
13442 17, 17); 14633 12, 12);
14634 state = interpreter->state;
13443 14635
13444 if (fpgm) 14636 if (fpgm)
13445 { 14637 {
@@ -13614,7 +14806,7 @@ main (int argc, char **argv)
13614 /* Time this important bit. */ 14806 /* Time this important bit. */
13615 clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); 14807 clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start);
13616 outline = sfnt_build_glyph_outline (glyph, head, 14808 outline = sfnt_build_glyph_outline (glyph, head,
13617 50, 14809 12,
13618 sfnt_test_get_glyph, 14810 sfnt_test_get_glyph,
13619 sfnt_test_free_glyph, 14811 sfnt_test_free_glyph,
13620 &dcontext); 14812 &dcontext);
@@ -13681,13 +14873,57 @@ main (int argc, char **argv)
13681 14873
13682 if (hmtx && head) 14874 if (hmtx && head)
13683 { 14875 {
13684 if (!sfnt_lookup_glyph_metrics (code, 50, 14876 if (!sfnt_lookup_glyph_metrics (code, 12,
13685 &metrics, 14877 &metrics,
13686 hmtx, hhea, 14878 hmtx, hhea,
13687 head, maxp)) 14879 head, maxp))
13688 printf ("lbearing, advance: %g, %g\n", 14880 printf ("lbearing, advance: %g, %g\n",
13689 sfnt_coerce_fixed (metrics.lbearing), 14881 sfnt_coerce_fixed (metrics.lbearing),
13690 sfnt_coerce_fixed (metrics.advance)); 14882 sfnt_coerce_fixed (metrics.advance));
14883
14884 if (interpreter)
14885 {
14886 if (getenv ("SFNT_DEBUG"))
14887 interpreter->run_hook = sfnt_run_hook;
14888 else if (getenv ("SFNT_VERBOSE"))
14889 interpreter->run_hook = sfnt_verbose;
14890
14891 if (glyph->simple
14892 && sfnt_lookup_glyph_metrics (code, -1,
14893 &metrics,
14894 hmtx, hhea,
14895 head, maxp))
14896 {
14897 printf ("interpreting glyph\n");
14898 interpreter->state = state;
14899 trap = sfnt_interpret_simple_glyph (glyph, interpreter,
14900 &metrics, &value);
14901
14902 if (trap)
14903 printf ("**TRAP**: %s\n", trap);
14904 else
14905 {
14906 printf ("rasterizing instructed outline\n");
14907 if (outline)
14908 xfree (outline);
14909 outline = sfnt_build_instructed_outline (value);
14910 xfree (value);
14911
14912 if (outline)
14913 {
14914 raster = sfnt_raster_glyph_outline (outline);
14915
14916 if (raster)
14917 {
14918 sfnt_test_raster (raster);
14919 xfree (raster);
14920 }
14921 }
14922 }
14923 }
14924
14925 interpreter->run_hook = NULL;
14926 }
13691 } 14927 }
13692 14928
13693 printf ("time spent outlining: %lld sec %ld nsec\n", 14929 printf ("time spent outlining: %lld sec %ld nsec\n",
diff --git a/src/sfnt.h b/src/sfnt.h
index ad8ba810dbb..baed1d257dd 100644
--- a/src/sfnt.h
+++ b/src/sfnt.h
@@ -731,6 +731,7 @@ enum
731 SFNT_POLY_MASK = (SFNT_POLY_SAMPLE - 1), 731 SFNT_POLY_MASK = (SFNT_POLY_SAMPLE - 1),
732 SFNT_POLY_STEP = (0x10000 >> SFNT_POLY_SHIFT), 732 SFNT_POLY_STEP = (0x10000 >> SFNT_POLY_SHIFT),
733 SFNT_POLY_START = (SFNT_POLY_STEP >> 1), 733 SFNT_POLY_START = (SFNT_POLY_STEP >> 1),
734 SFNT_POLY_ROUND = ((1 << (16 - SFNT_POLY_SHIFT)) / 2) - 1,
734 }; 735 };
735 736
736 737