diff options
| author | Po Lu | 2023-02-06 21:19:04 +0800 |
|---|---|---|
| committer | Po Lu | 2023-02-06 21:19:04 +0800 |
| commit | 7275e32d0b0db412d6a20b3d656ef72ea72d8a44 (patch) | |
| tree | c6dd2c925198c92b3b68d04f0c8b001cc5c00422 | |
| parent | 98c90135fe5f3729a3fa6e9a724d04a78b2cd514 (diff) | |
| download | emacs-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.c | 1646 | ||||
| -rw-r--r-- | src/sfnt.h | 1 |
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 | ||
| 47 | static void * | 51 | static void * |
| 48 | xmalloc (size_t size) | 52 | xmalloc (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 | ||
| 6947 | static void | 7056 | static void |
| 6948 | sfnt_save_projection_vector (struct sfnt_interpreter *interpreter, | 7057 | sfnt_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 | |||
| 7326 | static void | ||
| 7327 | sfnt_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 | |||
| 7493 | static void | ||
| 7494 | sfnt_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 | |||
| 7512 | static void | ||
| 7513 | sfnt_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 | |||
| 7532 | static void | ||
| 7533 | sfnt_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 | ||
| 7363 | static void | 7569 | static void |
| 7364 | sfnt_interpret_scfs (struct sfnt_interpreter *interpreter, | 7570 | sfnt_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 | ||
| 7753 | static void | 7999 | static void |
| 7754 | sfnt_line_to_vector (struct sfnt_interpreter *interpreter, | 8000 | sfnt_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 | ||
| 7836 | static void | 8087 | static void |
| 7837 | sfnt_interpret_msirp (struct sfnt_interpreter *interpreter, | 8088 | sfnt_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 | |||
| 9733 | static void | ||
| 9734 | sfnt_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 | |||
| 9867 | static void | ||
| 9868 | sfnt_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 | ||
| 10097 | struct sfnt_scaled_outline | 10619 | struct 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 | |||
| 10663 | static int | ||
| 10664 | sfnt_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 | |||
| 10799 | static struct sfnt_glyph_outline * | ||
| 10800 | sfnt_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 * | |||
| 10160 | sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph, | 10889 | sfnt_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. */ | ||
| 13997 | static Display *display; | ||
| 13998 | |||
| 13999 | /* The debugger window. */ | ||
| 14000 | static Window window; | ||
| 14001 | |||
| 14002 | /* The GC. */ | ||
| 14003 | static GC point_gc, background_gc; | ||
| 14004 | |||
| 14005 | static void | ||
| 14006 | sfnt_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 | |||
| 14042 | static const char * | ||
| 14043 | sfnt_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 | |||
| 14327 | static void | ||
| 14328 | sfnt_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 | |||
| 14380 | static void | ||
| 14381 | sfnt_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 | |||
| 14417 | static void | ||
| 14418 | sfnt_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 | ||