diff options
| author | Po Lu | 2023-02-07 22:25:54 +0800 |
|---|---|---|
| committer | Po Lu | 2023-02-07 22:25:54 +0800 |
| commit | 795f5a16b56a757fbb77562f47aaa4513ca52dbc (patch) | |
| tree | deb9862ce9e62e9023a93b4b4b66b3f5a3a82146 /src | |
| parent | 9b79f429edd173efd6ecbdcb2f0a5fafa8d6e523 (diff) | |
| download | emacs-795f5a16b56a757fbb77562f47aaa4513ca52dbc.tar.gz emacs-795f5a16b56a757fbb77562f47aaa4513ca52dbc.zip | |
Update Android port
* INSTALL.android: Describe patches for BoringSSL on ARM.
* src/sfnt.c (sfnt_build_glyph_outline): Remove redundant
multiplication.
(sfnt_prepare_raster): Update offset calculation for changes.
(sfnt_step_edge, sfnt_step_edge_n): Handle bresenham terms.
(sfnt_build_outline_edges): Don't subtract floored xmin, just
xmin.
(sfnt_saturate_short): Make clang generate better code.
(sfnt_fill_span): Stop rounding coordinates.
(sfnt_poly_span): Poly consecutive on transitions all in one go.
(sfnt_lookup_glyph_metrics): Remove redundant multiplication.
(struct sfnt_interpreter): New hooks for debugging.
(sfnt_large_integer_add): New function.
(sfnt_mul_f26dot6_fixed): Round product.
(sfnt_make_interpreter): Remove redundant multiplication.
(CHECK_STACK_ELEMENTS, POP_UNCHECKED, PUSH_UNCHECKED): New
macros.
(MOVE, POP, SWAP, CINDEX, RS, RCVT, LT, LTEQ, GT, GTEQ, EQ, NEQ)
(EVEN, AND, OR, NOT, ADD, SUB, DIV, MUL, ABS, NEG, FLOOR, CEILING)
(GETINFO, ROLL, _MAX, _MIN, ROUND, NROUND, GC, MD): Don't check
SP redundantly, especially when pushing an element right after
popping one.
(sfnt_move_glyph_zone): Don't touch points by passing NULL as
flags.
(sfnt_direct_move_zp2): Touch P in the directions of the
movement.
(sfnt_interpret_scfs): Fix coding style.
(sfnt_interpret_simple_glyph): Don't round Y coordinates.
(sfnt_test_span, sfnt_test_edges, sfnt_debug_edges, sfnt_test_edge)
(sfnt_x_raster, sfnt_test_raster, rcvt_test_args)
(deltac1_test_args, deltac2_test_args, deltac3_test_args)
(roll_1_test_args, sfnt_run_hook, sfnt_identify_instruction)
(sfnt_verbose, main): Improve debug code and tests.
* src/sfnt.h (struct sfnt_edge): Add bresenham terms.
Diffstat (limited to 'src')
| -rw-r--r-- | src/sfnt.c | 769 | ||||
| -rw-r--r-- | src/sfnt.h | 21 |
2 files changed, 639 insertions, 151 deletions
diff --git a/src/sfnt.c b/src/sfnt.c index 124185a5073..13a73f057bd 100644 --- a/src/sfnt.c +++ b/src/sfnt.c | |||
| @@ -47,6 +47,7 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| 47 | #include <errno.h> | 47 | #include <errno.h> |
| 48 | 48 | ||
| 49 | #include <X11/Xlib.h> | 49 | #include <X11/Xlib.h> |
| 50 | #include <X11/extensions/Xrender.h> | ||
| 50 | 51 | ||
| 51 | static void * | 52 | static void * |
| 52 | xmalloc (size_t size) | 53 | xmalloc (size_t size) |
| @@ -3489,8 +3490,7 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph, | |||
| 3489 | PIXEL = UNIT * PPEM / UPEM */ | 3490 | PIXEL = UNIT * PPEM / UPEM */ |
| 3490 | 3491 | ||
| 3491 | build_outline_context.factor | 3492 | build_outline_context.factor |
| 3492 | = sfnt_div_fixed (pixel_size * 65536, | 3493 | = sfnt_div_fixed (pixel_size, head->units_per_em); |
| 3493 | head->units_per_em * 65536); | ||
| 3494 | 3494 | ||
| 3495 | /* Decompose the outline. */ | 3495 | /* Decompose the outline. */ |
| 3496 | rc = sfnt_decompose_glyph (glyph, sfnt_move_to_and_build, | 3496 | rc = sfnt_decompose_glyph (glyph, sfnt_move_to_and_build, |
| @@ -3566,10 +3566,8 @@ sfnt_prepare_raster (struct sfnt_raster *raster, | |||
| 3566 | + (SFNT_POLY_ALIGNMENT - 1)) | 3566 | + (SFNT_POLY_ALIGNMENT - 1)) |
| 3567 | & ~(SFNT_POLY_ALIGNMENT - 1)); | 3567 | & ~(SFNT_POLY_ALIGNMENT - 1)); |
| 3568 | 3568 | ||
| 3569 | raster->offx | 3569 | raster->offx = sfnt_round_fixed (outline->xmin) >> 16; |
| 3570 | = sfnt_floor_fixed (outline->xmin) >> 16; | 3570 | raster->offy = sfnt_floor_fixed (outline->ymin) >> 16; |
| 3571 | raster->offy | ||
| 3572 | = sfnt_floor_fixed (outline->ymin) >> 16; | ||
| 3573 | } | 3571 | } |
| 3574 | 3572 | ||
| 3575 | typedef void (*sfnt_edge_proc) (struct sfnt_edge *, size_t, | 3573 | typedef void (*sfnt_edge_proc) (struct sfnt_edge *, size_t, |
| @@ -3582,15 +3580,41 @@ typedef void (*sfnt_span_proc) (struct sfnt_edge *, sfnt_fixed, void *); | |||
| 3582 | static void | 3580 | static void |
| 3583 | sfnt_step_edge (struct sfnt_edge *edge) | 3581 | sfnt_step_edge (struct sfnt_edge *edge) |
| 3584 | { | 3582 | { |
| 3585 | /* Step edge. */ | 3583 | /* Add error accumulator. */ |
| 3586 | edge->x += edge->step_x; | 3584 | edge->error += edge->step_x; |
| 3585 | |||
| 3586 | while (edge->error > 0) | ||
| 3587 | { | ||
| 3588 | /* Subtract error and add 1. */ | ||
| 3589 | edge->x += edge->signed_step; | ||
| 3590 | edge->error -= 65536; | ||
| 3591 | } | ||
| 3587 | } | 3592 | } |
| 3588 | 3593 | ||
| 3589 | /* Build a list of edges for each contour in OUTLINE, applying | 3594 | /* Move EDGE->x forward, assuming that the scanline has moved upwards |
| 3590 | OUTLINE->xmin and floor (OUTLINE->ymin) as the offset to each edge. | 3595 | by N, and that N is less than or equal to SFNT_POLY_STEP. */ |
| 3591 | Call EDGE_PROC with DCONTEXT and the resulting edges as arguments. | 3596 | |
| 3592 | It is OK to modify the edges given to EDGE_PROC. Align all edges | 3597 | static void |
| 3593 | to the sub-pixel grid. */ | 3598 | sfnt_step_edge_n (struct sfnt_edge *edge, sfnt_fixed n) |
| 3599 | { | ||
| 3600 | /* Add error accumulator. */ | ||
| 3601 | edge->error += sfnt_mul_fixed (edge->step_x, n); | ||
| 3602 | |||
| 3603 | /* See if error is more than 0, and bring the line back to where it | ||
| 3604 | should be. */ | ||
| 3605 | |||
| 3606 | while (edge->error > 0) | ||
| 3607 | { | ||
| 3608 | /* Subtract error and add 1. */ | ||
| 3609 | edge->x += edge->signed_step; | ||
| 3610 | edge->error -= 65536; | ||
| 3611 | } | ||
| 3612 | } | ||
| 3613 | |||
| 3614 | /* Build a list of edges for each contour in OUTLINE, applying xmin | ||
| 3615 | and ymin as the offset to each edge. Call EDGE_PROC with DCONTEXT | ||
| 3616 | and the resulting edges as arguments. It is OK to modify the edges | ||
| 3617 | given to EDGE_PROC. Align all edges to the sub-pixel grid. */ | ||
| 3594 | 3618 | ||
| 3595 | static void | 3619 | static void |
| 3596 | sfnt_build_outline_edges (struct sfnt_glyph_outline *outline, | 3620 | sfnt_build_outline_edges (struct sfnt_glyph_outline *outline, |
| @@ -3606,9 +3630,10 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline, | |||
| 3606 | edge = 0; | 3630 | edge = 0; |
| 3607 | 3631 | ||
| 3608 | /* ymin and xmin must be the same as the offset used to set offy and | 3632 | /* ymin and xmin must be the same as the offset used to set offy and |
| 3609 | offx in rasters. */ | 3633 | offx in rasters. However, xmin is not floored; otherwise, glyphs |
| 3634 | like ``e'' look bad at certain ppem. */ | ||
| 3610 | ymin = sfnt_floor_fixed (outline->ymin); | 3635 | ymin = sfnt_floor_fixed (outline->ymin); |
| 3611 | xmin = sfnt_floor_fixed (outline->xmin); | 3636 | xmin = outline->xmin; |
| 3612 | 3637 | ||
| 3613 | for (i = 0; i < outline->outline_used; ++i) | 3638 | for (i = 0; i < outline->outline_used; ++i) |
| 3614 | { | 3639 | { |
| @@ -3666,9 +3691,21 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline, | |||
| 3666 | dy = abs (outline->outline[top].y | 3691 | dy = abs (outline->outline[top].y |
| 3667 | - outline->outline[bottom].y); | 3692 | - outline->outline[bottom].y); |
| 3668 | 3693 | ||
| 3669 | #ifdef TEST | 3694 | /* Step to first grid point. */ |
| 3670 | edges[edge].source_x = edges[edge].x; | 3695 | y = sfnt_poly_grid_ceil (bot); |
| 3671 | #endif | 3696 | |
| 3697 | /* If rounding would make the edge not cover any area, skip this | ||
| 3698 | edge. */ | ||
| 3699 | if (y >= edges[edge].top) | ||
| 3700 | continue; | ||
| 3701 | |||
| 3702 | /* Compute the slope error. This is how much X changes for each | ||
| 3703 | increase in Y. */ | ||
| 3704 | |||
| 3705 | if (dx >= 0) | ||
| 3706 | step_x = sfnt_div_fixed (dx, dy); | ||
| 3707 | else | ||
| 3708 | step_x = sfnt_div_fixed (-dx, dy); | ||
| 3672 | 3709 | ||
| 3673 | /* Compute the increment. This is which direction X moves in | 3710 | /* Compute the increment. This is which direction X moves in |
| 3674 | for each increase in Y. */ | 3711 | for each increase in Y. */ |
| @@ -3676,30 +3713,19 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline, | |||
| 3676 | if (dx >= 0) | 3713 | if (dx >= 0) |
| 3677 | inc_x = 1; | 3714 | inc_x = 1; |
| 3678 | else | 3715 | else |
| 3679 | { | 3716 | inc_x = -1; |
| 3680 | inc_x = -1; | ||
| 3681 | dx = -dx; | ||
| 3682 | } | ||
| 3683 | 3717 | ||
| 3684 | /* Compute the step X. This is how much X changes for each | 3718 | edges[edge].signed_step = SFNT_POLY_STEP * inc_x; |
| 3685 | increase in Y. */ | 3719 | edges[edge].next = NULL; |
| 3686 | step_x = inc_x * sfnt_div_fixed (dx, dy); | ||
| 3687 | 3720 | ||
| 3688 | /* Step to first grid point. */ | 3721 | /* Set the initial Bresenham terms. */ |
| 3689 | y = sfnt_poly_grid_ceil (bot); | 3722 | edges[edge].error = step_x - 65536; |
| 3723 | edges[edge].step_x = step_x; | ||
| 3690 | 3724 | ||
| 3691 | /* If rounding would make the edge not cover any area, skip this | 3725 | sfnt_step_edge_n (&edges[edge], bot - y); |
| 3692 | edge. */ | ||
| 3693 | if (y > edges[edge].top) | ||
| 3694 | continue; | ||
| 3695 | 3726 | ||
| 3696 | edges[edge].x += sfnt_mul_fixed (step_x, bot - y); | 3727 | /* Set the bottom position. */ |
| 3697 | edges[edge].bottom = y; | 3728 | edges[edge].bottom = y; |
| 3698 | edges[edge].next = NULL; | ||
| 3699 | |||
| 3700 | /* Compute the step X scaled to the poly step. */ | ||
| 3701 | edges[edge].step_x | ||
| 3702 | = sfnt_mul_fixed (step_x, SFNT_POLY_STEP); | ||
| 3703 | 3729 | ||
| 3704 | edge++; | 3730 | edge++; |
| 3705 | } | 3731 | } |
| @@ -3741,7 +3767,16 @@ sfnt_compare_edges (const void *a, const void *b) | |||
| 3741 | coordinates, and incrementing the Y axis by SFNT_POLY_STEP instead | 3767 | coordinates, and incrementing the Y axis by SFNT_POLY_STEP instead |
| 3742 | of 1. SFNT_POLY_STEP is chosen to always keep Y aligned to a grid | 3768 | of 1. SFNT_POLY_STEP is chosen to always keep Y aligned to a grid |
| 3743 | placed such that there are always 1 << SFNT_POLY_SHIFT positions | 3769 | placed such that there are always 1 << SFNT_POLY_SHIFT positions |
| 3744 | available for each integral pixel coordinate. */ | 3770 | available for each integral pixel coordinate. |
| 3771 | |||
| 3772 | Moving upwards is performed using Bresenham's algorithm. Prior to | ||
| 3773 | an edge being created, a single slope error is computed. This is | ||
| 3774 | how much X should increase for each increase in Y. | ||
| 3775 | |||
| 3776 | Upon each increase in Y, X initially does not move. Instead, the | ||
| 3777 | ``slope error'' is accumulated; once it exceeds the sample size, | ||
| 3778 | one sample is subtracted from the accumulator, and X is increased | ||
| 3779 | by one step. */ | ||
| 3745 | 3780 | ||
| 3746 | static void | 3781 | static void |
| 3747 | sfnt_poly_edges (struct sfnt_edge *edges, size_t size, | 3782 | sfnt_poly_edges (struct sfnt_edge *edges, size_t size, |
| @@ -3822,13 +3857,16 @@ sfnt_poly_edges (struct sfnt_edge *edges, size_t size, | |||
| 3822 | } | 3857 | } |
| 3823 | } | 3858 | } |
| 3824 | 3859 | ||
| 3825 | /* Saturate-convert the given unsigned short value X to an unsigned | 3860 | /* Saturate and convert the given unsigned short value X to an |
| 3826 | char. */ | 3861 | unsigned char. */ |
| 3827 | 3862 | ||
| 3828 | static unsigned char | 3863 | static unsigned char |
| 3829 | sfnt_saturate_short (unsigned short x) | 3864 | sfnt_saturate_short (unsigned short x) |
| 3830 | { | 3865 | { |
| 3831 | return (unsigned char) ((x) | (0 - ((x) >> 8))); | 3866 | if (x > 255) |
| 3867 | return 255; | ||
| 3868 | |||
| 3869 | return x; | ||
| 3832 | } | 3870 | } |
| 3833 | 3871 | ||
| 3834 | /* Fill a single span of pixels between X0 and X1 at Y, a raster | 3872 | /* Fill a single span of pixels between X0 and X1 at Y, a raster |
| @@ -3855,11 +3893,6 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, | |||
| 3855 | if (x1 <= x0) | 3893 | if (x1 <= x0) |
| 3856 | return; | 3894 | return; |
| 3857 | 3895 | ||
| 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. */ | 3896 | /* Figure out coverage based on Y axis fractional. */ |
| 3864 | coverage = sfnt_poly_coverage[(y >> (16 - SFNT_POLY_SHIFT)) | 3897 | coverage = sfnt_poly_coverage[(y >> (16 - SFNT_POLY_SHIFT)) |
| 3865 | & SFNT_POLY_MASK]; | 3898 | & SFNT_POLY_MASK]; |
| @@ -3882,11 +3915,11 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, | |||
| 3882 | #endif | 3915 | #endif |
| 3883 | start += left >> SFNT_POLY_SHIFT; | 3916 | start += left >> SFNT_POLY_SHIFT; |
| 3884 | 3917 | ||
| 3918 | w = 0; | ||
| 3919 | |||
| 3885 | /* Compute coverage for first pixel, then poly. */ | 3920 | /* Compute coverage for first pixel, then poly. */ |
| 3886 | if (left & SFNT_POLY_MASK) | 3921 | if (left & SFNT_POLY_MASK) |
| 3887 | { | 3922 | { |
| 3888 | w = 0; | ||
| 3889 | |||
| 3890 | /* Note that col is an index into the columns of the coverage | 3923 | /* Note that col is an index into the columns of the coverage |
| 3891 | map, unlike row which indexes the raster. */ | 3924 | map, unlike row which indexes the raster. */ |
| 3892 | col = 0; | 3925 | col = 0; |
| @@ -3941,24 +3974,47 @@ sfnt_poly_span (struct sfnt_edge *start, sfnt_fixed y, | |||
| 3941 | { | 3974 | { |
| 3942 | struct sfnt_edge *edge; | 3975 | struct sfnt_edge *edge; |
| 3943 | int winding; | 3976 | int winding; |
| 3944 | sfnt_fixed x0; | 3977 | sfnt_fixed x0, x1; |
| 3978 | |||
| 3979 | /* Pacify -Wmaybe-uninitialized; x1 and x0 are only used when edge | ||
| 3980 | != start, at which point x0 has already been set. */ | ||
| 3981 | x0 = x1 = 0; | ||
| 3945 | 3982 | ||
| 3946 | /* Generate the X axis coverage map. Then poly it onto RASTER. | 3983 | /* Generate the X axis coverage map. Then poly it onto RASTER. |
| 3947 | winding on each edge determines the winding direction: when it is | 3984 | winding on each edge determines the winding direction: when it is |
| 3948 | positive, winding is 1. When it is negative, winding is -1. */ | 3985 | positive, winding is 1. When it is negative, winding is -1. |
| 3986 | |||
| 3987 | Fill each consecutive stretch of spans that are inside the glyph; | ||
| 3988 | otherwise, coverage will overlap for some spans, but not | ||
| 3989 | others. | ||
| 3990 | |||
| 3991 | The spans must be terminated with an edge that causes an | ||
| 3992 | off-transition, or some spans will not be filled. */ | ||
| 3949 | 3993 | ||
| 3950 | winding = 0; | 3994 | winding = 0; |
| 3951 | 3995 | ||
| 3952 | for (edge = start; edge; edge = edge->next) | 3996 | for (edge = start; edge; edge = edge->next) |
| 3953 | { | 3997 | { |
| 3954 | if (!winding) | 3998 | if (!winding) |
| 3955 | x0 = edge->x; | 3999 | { |
| 4000 | if (edge != start && x0 != x1) | ||
| 4001 | /* Draw this section of spans that are on. */ | ||
| 4002 | sfnt_fill_span (raster, (raster->height << 16) - y, | ||
| 4003 | x0, x1); | ||
| 4004 | |||
| 4005 | x0 = x1 = edge->x; | ||
| 4006 | } | ||
| 3956 | else | 4007 | else |
| 3957 | sfnt_fill_span (raster, (raster->height << 16) - y, | 4008 | x1 = edge->x; |
| 3958 | x0, edge->x); | ||
| 3959 | 4009 | ||
| 3960 | winding += edge->winding; | 4010 | winding += edge->winding; |
| 3961 | } | 4011 | } |
| 4012 | |||
| 4013 | /* Draw the last span following the last off-transition. */ | ||
| 4014 | |||
| 4015 | if (!winding && edge != start && x0 != x1) | ||
| 4016 | sfnt_fill_span (raster, (raster->height << 16) - y, | ||
| 4017 | x0, x1); | ||
| 3962 | } | 4018 | } |
| 3963 | 4019 | ||
| 3964 | 4020 | ||
| @@ -4143,8 +4199,7 @@ sfnt_lookup_glyph_metrics (sfnt_glyph glyph, int pixel_size, | |||
| 4143 | } | 4199 | } |
| 4144 | 4200 | ||
| 4145 | /* Now scale lbearing and advance up to the pixel size. */ | 4201 | /* Now scale lbearing and advance up to the pixel size. */ |
| 4146 | factor = sfnt_div_fixed (pixel_size << 16, | 4202 | factor = sfnt_div_fixed (pixel_size, head->units_per_em); |
| 4147 | head->units_per_em << 16); | ||
| 4148 | 4203 | ||
| 4149 | /* Save them. */ | 4204 | /* Save them. */ |
| 4150 | metrics->lbearing = sfnt_mul_fixed (lbearing << 16, factor); | 4205 | metrics->lbearing = sfnt_mul_fixed (lbearing << 16, factor); |
| @@ -5148,6 +5203,14 @@ struct sfnt_interpreter | |||
| 5148 | /* If non-NULL, function called before each instruction is | 5203 | /* If non-NULL, function called before each instruction is |
| 5149 | executed. */ | 5204 | executed. */ |
| 5150 | void (*run_hook) (struct sfnt_interpreter *); | 5205 | void (*run_hook) (struct sfnt_interpreter *); |
| 5206 | |||
| 5207 | /* If non-NULL, function called before each stack element is | ||
| 5208 | pushed. */ | ||
| 5209 | void (*push_hook) (struct sfnt_interpreter *, uint32_t); | ||
| 5210 | |||
| 5211 | /* If non-NULL, function called before each stack element is | ||
| 5212 | popped. */ | ||
| 5213 | void (*pop_hook) (struct sfnt_interpreter *, uint32_t); | ||
| 5151 | #endif | 5214 | #endif |
| 5152 | }; | 5215 | }; |
| 5153 | 5216 | ||
| @@ -5239,8 +5302,28 @@ sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) | |||
| 5239 | #endif | 5302 | #endif |
| 5240 | } | 5303 | } |
| 5241 | 5304 | ||
| 5305 | #ifndef INT64_MAX | ||
| 5306 | |||
| 5307 | /* Add the specified unsigned 32-bit N to the large integer | ||
| 5308 | INTEGER. */ | ||
| 5309 | |||
| 5310 | static void | ||
| 5311 | sfnt_large_integer_add (struct sfnt_large_integer *integer, | ||
| 5312 | uint32_t n) | ||
| 5313 | { | ||
| 5314 | struct sfnt_large_integer number; | ||
| 5315 | |||
| 5316 | number.low = integer->low + n; | ||
| 5317 | number.high = integer->high + (number.low | ||
| 5318 | < integer->low); | ||
| 5319 | |||
| 5320 | *integer = number; | ||
| 5321 | } | ||
| 5322 | |||
| 5323 | #endif | ||
| 5324 | |||
| 5242 | /* Multiply the specified 26.6 fixed point number X by the specified | 5325 | /* Multiply the specified 26.6 fixed point number X by the specified |
| 5243 | 16.16 fixed point number Y. | 5326 | 16.16 fixed point number Y with symmetric rounding. |
| 5244 | 5327 | ||
| 5245 | The 26.6 fixed point number must fit inside -32768 to 32767.ffff. | 5328 | The 26.6 fixed point number must fit inside -32768 to 32767.ffff. |
| 5246 | Value is otherwise undefined. */ | 5329 | Value is otherwise undefined. */ |
| @@ -5248,10 +5331,44 @@ sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) | |||
| 5248 | static sfnt_f26dot6 | 5331 | static sfnt_f26dot6 |
| 5249 | sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y) | 5332 | sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y) |
| 5250 | { | 5333 | { |
| 5251 | sfnt_fixed result; | 5334 | #ifdef INT64_MAX |
| 5335 | uint64_t product; | ||
| 5336 | int sign; | ||
| 5252 | 5337 | ||
| 5253 | result = sfnt_mul_fixed (y, x); | 5338 | sign = 1; |
| 5254 | return result; | 5339 | |
| 5340 | if (x < 0) | ||
| 5341 | { | ||
| 5342 | x = -x; | ||
| 5343 | sign = -sign; | ||
| 5344 | } | ||
| 5345 | |||
| 5346 | if (y < 0) | ||
| 5347 | { | ||
| 5348 | y = -y; | ||
| 5349 | sign = -sign; | ||
| 5350 | } | ||
| 5351 | |||
| 5352 | product = (uint64_t) y * (uint64_t) x; | ||
| 5353 | |||
| 5354 | /* This can be done quickly with int64_t. */ | ||
| 5355 | return ((int64_t) (product + 32676) / (int64_t) 65536) * sign; | ||
| 5356 | #else | ||
| 5357 | struct sfnt_large_integer temp; | ||
| 5358 | int sign; | ||
| 5359 | |||
| 5360 | sign = 1; | ||
| 5361 | |||
| 5362 | if (x < 0) | ||
| 5363 | sign = -sign; | ||
| 5364 | |||
| 5365 | if (y < 0) | ||
| 5366 | sign = -sign; | ||
| 5367 | |||
| 5368 | sfnt_multiply_divide_1 (abs (x), abs (y), &temp); | ||
| 5369 | sfnt_large_integer_add (&temp, 32676); | ||
| 5370 | return sfnt_multiply_divide_2 (&temp, 65536) * sign; | ||
| 5371 | #endif | ||
| 5255 | } | 5372 | } |
| 5256 | 5373 | ||
| 5257 | /* Return the floor of the specified 26.6 fixed point value X. */ | 5374 | /* Return the floor of the specified 26.6 fixed point value X. */ |
| @@ -5411,6 +5528,8 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp, | |||
| 5411 | 5528 | ||
| 5412 | #ifdef TEST | 5529 | #ifdef TEST |
| 5413 | interpreter->run_hook = NULL; | 5530 | interpreter->run_hook = NULL; |
| 5531 | interpreter->push_hook = NULL; | ||
| 5532 | interpreter->pop_hook = NULL; | ||
| 5414 | #endif | 5533 | #endif |
| 5415 | 5534 | ||
| 5416 | /* Fill in pointers and default values. */ | 5535 | /* Fill in pointers and default values. */ |
| @@ -5461,8 +5580,7 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp, | |||
| 5461 | /* Now compute the scale. Then, scale up the control value table | 5580 | /* Now compute the scale. Then, scale up the control value table |
| 5462 | values. */ | 5581 | values. */ |
| 5463 | interpreter->scale | 5582 | interpreter->scale |
| 5464 | = sfnt_div_fixed (pixel_size * 64, | 5583 | = sfnt_div_fixed (pixel_size, head->units_per_em); |
| 5465 | head->units_per_em * 64); | ||
| 5466 | 5584 | ||
| 5467 | /* Set the PPEM. */ | 5585 | /* Set the PPEM. */ |
| 5468 | interpreter->ppem = pixel_size; | 5586 | interpreter->ppem = pixel_size; |
| @@ -5537,6 +5655,13 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 5537 | #define MOVE(a, b, n) \ | 5655 | #define MOVE(a, b, n) \ |
| 5538 | memmove (a, b, (n) * sizeof (uint32_t)) | 5656 | memmove (a, b, (n) * sizeof (uint32_t)) |
| 5539 | 5657 | ||
| 5658 | #define CHECK_STACK_ELEMENTS(n) \ | ||
| 5659 | { \ | ||
| 5660 | if ((interpreter->SP \ | ||
| 5661 | - interpreter->stack) < n) \ | ||
| 5662 | TRAP ("stack underflow"); \ | ||
| 5663 | } | ||
| 5664 | |||
| 5540 | #define CHECK_PREP() \ | 5665 | #define CHECK_PREP() \ |
| 5541 | if (!is_prep) \ | 5666 | if (!is_prep) \ |
| 5542 | TRAP ("instruction executed not valid" \ | 5667 | TRAP ("instruction executed not valid" \ |
| @@ -5555,26 +5680,88 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 5555 | 5680 | ||
| 5556 | /* Register, alu and logic instructions. */ | 5681 | /* Register, alu and logic instructions. */ |
| 5557 | 5682 | ||
| 5683 | #ifndef TEST | ||
| 5684 | |||
| 5558 | #define POP() \ | 5685 | #define POP() \ |
| 5559 | (interpreter->SP == interpreter->stack \ | 5686 | (interpreter->SP == interpreter->stack \ |
| 5560 | ? (TRAP ("stack underflow"), 0) \ | 5687 | ? (TRAP ("stack underflow"), 0) \ |
| 5561 | : (*(--interpreter->SP))) | 5688 | : (*(--interpreter->SP))) |
| 5562 | 5689 | ||
| 5690 | #define POP_UNCHECKED() (*(--interpreter->SP)) | ||
| 5691 | |||
| 5692 | #else | ||
| 5693 | |||
| 5694 | #define POP() \ | ||
| 5695 | (interpreter->SP == interpreter->stack \ | ||
| 5696 | ? (TRAP ("stack underflow"), 0) \ | ||
| 5697 | : ({uint32_t _value; \ | ||
| 5698 | _value = *(--interpreter->SP); \ | ||
| 5699 | if (interpreter->pop_hook) \ | ||
| 5700 | interpreter->pop_hook (interpreter, \ | ||
| 5701 | _value); \ | ||
| 5702 | _value;})) | ||
| 5703 | |||
| 5704 | #define POP_UNCHECKED() \ | ||
| 5705 | ({uint32_t _value; \ | ||
| 5706 | _value = *(--interpreter->SP); \ | ||
| 5707 | if (interpreter->pop_hook) \ | ||
| 5708 | interpreter->pop_hook (interpreter, \ | ||
| 5709 | _value); \ | ||
| 5710 | _value;}) | ||
| 5711 | |||
| 5712 | #endif | ||
| 5713 | |||
| 5563 | #define LOOK() \ | 5714 | #define LOOK() \ |
| 5564 | (interpreter->SP == interpreter->stack \ | 5715 | (interpreter->SP == interpreter->stack \ |
| 5565 | ? (TRAP ("stack underflow"), 0) \ | 5716 | ? (TRAP ("stack underflow"), 0) \ |
| 5566 | : *(interpreter->SP - 1)) | 5717 | : *(interpreter->SP - 1)) |
| 5567 | 5718 | ||
| 5719 | #ifndef TEST | ||
| 5720 | |||
| 5721 | #define PUSH(value) \ | ||
| 5722 | { \ | ||
| 5723 | if ((char *) (interpreter->SP + 1) \ | ||
| 5724 | > (char *) interpreter->twilight_x) \ | ||
| 5725 | TRAP ("stack overflow"); \ | ||
| 5726 | \ | ||
| 5727 | *interpreter->SP = (value); \ | ||
| 5728 | interpreter->SP++; \ | ||
| 5729 | } | ||
| 5730 | |||
| 5731 | #define PUSH_UNCHECKED(value) \ | ||
| 5732 | { \ | ||
| 5733 | *interpreter->SP = (value); \ | ||
| 5734 | interpreter->SP++; \ | ||
| 5735 | } | ||
| 5736 | |||
| 5737 | #else | ||
| 5738 | |||
| 5568 | #define PUSH(value) \ | 5739 | #define PUSH(value) \ |
| 5569 | { \ | 5740 | { \ |
| 5570 | if ((char *) (interpreter->SP + 1) \ | 5741 | if ((char *) (interpreter->SP + 1) \ |
| 5571 | > (char *) interpreter->twilight_x) \ | 5742 | > (char *) interpreter->twilight_x) \ |
| 5572 | TRAP ("stack overflow"); \ | 5743 | TRAP ("stack overflow"); \ |
| 5573 | \ | 5744 | \ |
| 5745 | if (interpreter->push_hook) \ | ||
| 5746 | interpreter->push_hook (interpreter, \ | ||
| 5747 | value); \ | ||
| 5748 | \ | ||
| 5574 | *interpreter->SP = value; \ | 5749 | *interpreter->SP = value; \ |
| 5575 | interpreter->SP++; \ | 5750 | interpreter->SP++; \ |
| 5576 | } | 5751 | } |
| 5577 | 5752 | ||
| 5753 | #define PUSH_UNCHECKED(value) \ | ||
| 5754 | { \ | ||
| 5755 | if (interpreter->push_hook) \ | ||
| 5756 | interpreter->push_hook (interpreter, \ | ||
| 5757 | value); \ | ||
| 5758 | \ | ||
| 5759 | *interpreter->SP = value; \ | ||
| 5760 | interpreter->SP++; \ | ||
| 5761 | } | ||
| 5762 | |||
| 5763 | #endif | ||
| 5764 | |||
| 5578 | #define PUSH2(high, low) \ | 5765 | #define PUSH2(high, low) \ |
| 5579 | { \ | 5766 | { \ |
| 5580 | PUSH ((int16_t) ((int8_t) high) << 8 \ | 5767 | PUSH ((int16_t) ((int8_t) high) << 8 \ |
| @@ -5746,8 +5933,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 5746 | a = POP (); \ | 5933 | a = POP (); \ |
| 5747 | b = POP (); \ | 5934 | b = POP (); \ |
| 5748 | \ | 5935 | \ |
| 5749 | PUSH (a); \ | 5936 | PUSH_UNCHECKED (a); \ |
| 5750 | PUSH (b); \ | 5937 | PUSH_UNCHECKED (b); \ |
| 5751 | } | 5938 | } |
| 5752 | 5939 | ||
| 5753 | #define DEPTH() \ | 5940 | #define DEPTH() \ |
| @@ -5768,7 +5955,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 5768 | if (index <= 0 || index > STACKSIZE ()) \ | 5955 | if (index <= 0 || index > STACKSIZE ()) \ |
| 5769 | TRAP ("stack overflow"); \ | 5956 | TRAP ("stack overflow"); \ |
| 5770 | \ | 5957 | \ |
| 5771 | PUSH (*(interpreter->SP - index)); \ | 5958 | PUSH_UNCHECKED (*(interpreter->SP \ |
| 5959 | - index)); \ | ||
| 5772 | } | 5960 | } |
| 5773 | 5961 | ||
| 5774 | #define MINDEX() \ | 5962 | #define MINDEX() \ |
| @@ -5934,14 +6122,15 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 5934 | 6122 | ||
| 5935 | #define RS() \ | 6123 | #define RS() \ |
| 5936 | { \ | 6124 | { \ |
| 5937 | uint32_t address; \ | 6125 | uint32_t address, value; \ |
| 5938 | \ | 6126 | \ |
| 5939 | address = POP (); \ | 6127 | address = POP (); \ |
| 5940 | \ | 6128 | \ |
| 5941 | if (address >= interpreter->storage_size) \ | 6129 | if (address >= interpreter->storage_size) \ |
| 5942 | TRAP ("invalid RS"); \ | 6130 | TRAP ("invalid RS"); \ |
| 5943 | \ | 6131 | \ |
| 5944 | PUSH (interpreter->storage[address]); \ | 6132 | value = interpreter->storage[address]; \ |
| 6133 | PUSH_UNCHECKED (value); \ | ||
| 5945 | } | 6134 | } |
| 5946 | 6135 | ||
| 5947 | #define WCVTP() \ | 6136 | #define WCVTP() \ |
| @@ -5969,7 +6158,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 5969 | TRAP ("out of bounds RCVT"); \ | 6158 | TRAP ("out of bounds RCVT"); \ |
| 5970 | \ | 6159 | \ |
| 5971 | value = interpreter->cvt[location]; \ | 6160 | value = interpreter->cvt[location]; \ |
| 5972 | PUSH (value); \ | 6161 | PUSH_UNCHECKED (value); \ |
| 5973 | } | 6162 | } |
| 5974 | 6163 | ||
| 5975 | #define MPPEM() \ | 6164 | #define MPPEM() \ |
| @@ -6004,7 +6193,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6004 | e2 = POP (); \ | 6193 | e2 = POP (); \ |
| 6005 | e1 = POP (); \ | 6194 | e1 = POP (); \ |
| 6006 | \ | 6195 | \ |
| 6007 | PUSH (e1 < e2 ? 1 : 0); \ | 6196 | PUSH_UNCHECKED (e1 < e2 ? 1 : 0); \ |
| 6008 | } | 6197 | } |
| 6009 | 6198 | ||
| 6010 | #define LTEQ() \ | 6199 | #define LTEQ() \ |
| @@ -6014,7 +6203,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6014 | e2 = POP (); \ | 6203 | e2 = POP (); \ |
| 6015 | e1 = POP (); \ | 6204 | e1 = POP (); \ |
| 6016 | \ | 6205 | \ |
| 6017 | PUSH (e1 <= e2 ? 1 : 0); \ | 6206 | PUSH_UNCHECKED (e1 <= e2 ? 1 : 0); \ |
| 6018 | } | 6207 | } |
| 6019 | 6208 | ||
| 6020 | #define GT() \ | 6209 | #define GT() \ |
| @@ -6024,7 +6213,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6024 | e2 = POP (); \ | 6213 | e2 = POP (); \ |
| 6025 | e1 = POP (); \ | 6214 | e1 = POP (); \ |
| 6026 | \ | 6215 | \ |
| 6027 | PUSH (e1 > e2 ? 1 : 0); \ | 6216 | PUSH_UNCHECKED (e1 > e2 ? 1 : 0); \ |
| 6028 | } | 6217 | } |
| 6029 | 6218 | ||
| 6030 | #define GTEQ() \ | 6219 | #define GTEQ() \ |
| @@ -6034,7 +6223,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6034 | e2 = POP (); \ | 6223 | e2 = POP (); \ |
| 6035 | e1 = POP (); \ | 6224 | e1 = POP (); \ |
| 6036 | \ | 6225 | \ |
| 6037 | PUSH (e1 >= e2 ? 1 : 0); \ | 6226 | PUSH_UNCHECKED (e1 >= e2 ? 1 : 0); \ |
| 6038 | } | 6227 | } |
| 6039 | 6228 | ||
| 6040 | #define EQ() \ | 6229 | #define EQ() \ |
| @@ -6044,7 +6233,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6044 | e1 = POP (); \ | 6233 | e1 = POP (); \ |
| 6045 | e2 = POP (); \ | 6234 | e2 = POP (); \ |
| 6046 | \ | 6235 | \ |
| 6047 | PUSH (e1 == e2 ? 1 : 0); \ | 6236 | PUSH_UNCHECKED (e1 == e2 ? 1 : 0); \ |
| 6048 | } | 6237 | } |
| 6049 | 6238 | ||
| 6050 | #define NEQ() \ | 6239 | #define NEQ() \ |
| @@ -6054,7 +6243,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6054 | e1 = POP (); \ | 6243 | e1 = POP (); \ |
| 6055 | e2 = POP (); \ | 6244 | e2 = POP (); \ |
| 6056 | \ | 6245 | \ |
| 6057 | PUSH (e1 != e2 ? 1 : 0); \ | 6246 | PUSH_UNCHECKED (e1 != e2 ? 1 : 0); \ |
| 6058 | } | 6247 | } |
| 6059 | 6248 | ||
| 6060 | #define ODD() \ | 6249 | #define ODD() \ |
| @@ -6073,6 +6262,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6073 | #define EVEN() \ | 6262 | #define EVEN() \ |
| 6074 | { \ | 6263 | { \ |
| 6075 | sfnt_f26dot6 e1, result; \ | 6264 | sfnt_f26dot6 e1, result; \ |
| 6265 | uint32_t value; \ | ||
| 6076 | \ | 6266 | \ |
| 6077 | e1 = POP (); \ | 6267 | e1 = POP (); \ |
| 6078 | result = abs (e1); \ | 6268 | result = abs (e1); \ |
| @@ -6080,7 +6270,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6080 | result \ | 6270 | result \ |
| 6081 | = interpreter->state.round (result, \ | 6271 | = interpreter->state.round (result, \ |
| 6082 | interpreter); \ | 6272 | interpreter); \ |
| 6083 | PUSH (((result & 127) == 64) ? 0 : 1); \ | 6273 | value = ((result & 127) == 64) ? 0 : 1; \ |
| 6274 | PUSH_UNCHECKED (value); \ | ||
| 6084 | } | 6275 | } |
| 6085 | 6276 | ||
| 6086 | #define IF() \ | 6277 | #define IF() \ |
| @@ -6104,7 +6295,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6104 | e1 = POP (); \ | 6295 | e1 = POP (); \ |
| 6105 | e2 = POP (); \ | 6296 | e2 = POP (); \ |
| 6106 | \ | 6297 | \ |
| 6107 | PUSH (e1 && e2 ? 1 : 0); \ | 6298 | PUSH_UNCHECKED (e1 && e2 ? 1 : 0); \ |
| 6108 | } | 6299 | } |
| 6109 | 6300 | ||
| 6110 | #define OR() \ | 6301 | #define OR() \ |
| @@ -6114,7 +6305,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6114 | e1 = POP (); \ | 6305 | e1 = POP (); \ |
| 6115 | e2 = POP (); \ | 6306 | e2 = POP (); \ |
| 6116 | \ | 6307 | \ |
| 6117 | PUSH (e1 || e2 ? 1 : 0); \ | 6308 | PUSH_UNCHECKED (e1 || e2 ? 1 : 0); \ |
| 6118 | } | 6309 | } |
| 6119 | 6310 | ||
| 6120 | #define NOT() \ | 6311 | #define NOT() \ |
| @@ -6123,7 +6314,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6123 | \ | 6314 | \ |
| 6124 | e1 = POP (); \ | 6315 | e1 = POP (); \ |
| 6125 | \ | 6316 | \ |
| 6126 | PUSH (!e1 ? 1 : 0); \ | 6317 | PUSH_UNCHECKED (!e1 ? 1 : 0); \ |
| 6127 | } | 6318 | } |
| 6128 | 6319 | ||
| 6129 | #define SDB() \ | 6320 | #define SDB() \ |
| @@ -6154,7 +6345,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6154 | n1 = POP (); \ | 6345 | n1 = POP (); \ |
| 6155 | n2 = POP (); \ | 6346 | n2 = POP (); \ |
| 6156 | \ | 6347 | \ |
| 6157 | PUSH (sfnt_add (n1, n2)); \ | 6348 | PUSH_UNCHECKED (sfnt_add (n1, n2)); \ |
| 6158 | } | 6349 | } |
| 6159 | 6350 | ||
| 6160 | #define SUB() \ | 6351 | #define SUB() \ |
| @@ -6164,7 +6355,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6164 | n2 = POP (); \ | 6355 | n2 = POP (); \ |
| 6165 | n1 = POP (); \ | 6356 | n1 = POP (); \ |
| 6166 | \ | 6357 | \ |
| 6167 | PUSH (sfnt_sub (n1, n2)); \ | 6358 | PUSH_UNCHECKED (sfnt_sub (n1, n2)); \ |
| 6168 | } | 6359 | } |
| 6169 | 6360 | ||
| 6170 | #define DIV() \ | 6361 | #define DIV() \ |
| @@ -6177,7 +6368,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6177 | if (!n2) \ | 6368 | if (!n2) \ |
| 6178 | TRAP ("DIV by 0"); \ | 6369 | TRAP ("DIV by 0"); \ |
| 6179 | \ | 6370 | \ |
| 6180 | PUSH (sfnt_div_f26dot6 (n1, n2)); \ | 6371 | PUSH_UNCHECKED (sfnt_div_f26dot6 (n1, n2)); \ |
| 6181 | } | 6372 | } |
| 6182 | 6373 | ||
| 6183 | #define MUL() \ | 6374 | #define MUL() \ |
| @@ -6187,7 +6378,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6187 | n2 = POP (); \ | 6378 | n2 = POP (); \ |
| 6188 | n1 = POP (); \ | 6379 | n1 = POP (); \ |
| 6189 | \ | 6380 | \ |
| 6190 | PUSH (sfnt_mul_f26dot6 (n2, n1)); \ | 6381 | PUSH_UNCHECKED (sfnt_mul_f26dot6 (n2, n1)); \ |
| 6191 | } | 6382 | } |
| 6192 | 6383 | ||
| 6193 | #define ABS() \ | 6384 | #define ABS() \ |
| @@ -6196,10 +6387,10 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6196 | \ | 6387 | \ |
| 6197 | n = POP (); \ | 6388 | n = POP (); \ |
| 6198 | \ | 6389 | \ |
| 6199 | if (n == INT_MIN) \ | 6390 | if (n == INT32_MIN) \ |
| 6200 | PUSH (0) \ | 6391 | PUSH_UNCHECKED (0) \ |
| 6201 | else \ | 6392 | else \ |
| 6202 | PUSH (n < 0 ? -n : n) \ | 6393 | PUSH_UNCHECKED (n < 0 ? -n : n) \ |
| 6203 | } | 6394 | } |
| 6204 | 6395 | ||
| 6205 | #define NEG() \ | 6396 | #define NEG() \ |
| @@ -6208,10 +6399,10 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6208 | \ | 6399 | \ |
| 6209 | n = POP (); \ | 6400 | n = POP (); \ |
| 6210 | \ | 6401 | \ |
| 6211 | if (n == INT_MIN) \ | 6402 | if (n == INT32_MIN) \ |
| 6212 | PUSH (0) \ | 6403 | PUSH_UNCHECKED (0) \ |
| 6213 | else \ | 6404 | else \ |
| 6214 | PUSH (-n) \ | 6405 | PUSH_UNCHECKED (-n) \ |
| 6215 | } | 6406 | } |
| 6216 | 6407 | ||
| 6217 | #define FLOOR() \ | 6408 | #define FLOOR() \ |
| @@ -6219,7 +6410,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6219 | sfnt_f26dot6 n; \ | 6410 | sfnt_f26dot6 n; \ |
| 6220 | \ | 6411 | \ |
| 6221 | n = POP (); \ | 6412 | n = POP (); \ |
| 6222 | PUSH (sfnt_floor_f26dot6 (n)); \ | 6413 | PUSH_UNCHECKED (sfnt_floor_f26dot6 (n)); \ |
| 6223 | } | 6414 | } |
| 6224 | 6415 | ||
| 6225 | #define CEILING() \ | 6416 | #define CEILING() \ |
| @@ -6227,7 +6418,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6227 | sfnt_f26dot6 n; \ | 6418 | sfnt_f26dot6 n; \ |
| 6228 | \ | 6419 | \ |
| 6229 | n = POP (); \ | 6420 | n = POP (); \ |
| 6230 | PUSH (sfnt_ceil_f26dot6 (n)); \ | 6421 | PUSH_UNCHECKED (sfnt_ceil_f26dot6 (n)); \ |
| 6231 | } | 6422 | } |
| 6232 | 6423 | ||
| 6233 | #define WCVTF() \ | 6424 | #define WCVTF() \ |
| @@ -6306,9 +6497,9 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6306 | selector = POP (); \ | 6497 | selector = POP (); \ |
| 6307 | \ | 6498 | \ |
| 6308 | if (selector & 1) \ | 6499 | if (selector & 1) \ |
| 6309 | PUSH (2) \ | 6500 | PUSH_UNCHECKED (2) \ |
| 6310 | else \ | 6501 | else \ |
| 6311 | PUSH (0) \ | 6502 | PUSH_UNCHECKED (0) \ |
| 6312 | } | 6503 | } |
| 6313 | 6504 | ||
| 6314 | #define IDEF() \ | 6505 | #define IDEF() \ |
| @@ -6324,13 +6515,15 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6324 | { \ | 6515 | { \ |
| 6325 | uint32_t a, b, c; \ | 6516 | uint32_t a, b, c; \ |
| 6326 | \ | 6517 | \ |
| 6327 | a = POP (); \ | 6518 | CHECK_STACK_ELEMENTS (3); \ |
| 6328 | b = POP (); \ | ||
| 6329 | c = POP (); \ | ||
| 6330 | \ | 6519 | \ |
| 6331 | PUSH (b); \ | 6520 | a = POP_UNCHECKED (); \ |
| 6332 | PUSH (a); \ | 6521 | b = POP_UNCHECKED (); \ |
| 6333 | PUSH (c); \ | 6522 | c = POP_UNCHECKED (); \ |
| 6523 | \ | ||
| 6524 | PUSH_UNCHECKED (b); \ | ||
| 6525 | PUSH_UNCHECKED (a); \ | ||
| 6526 | PUSH_UNCHECKED (c); \ | ||
| 6334 | } | 6527 | } |
| 6335 | 6528 | ||
| 6336 | #define _MAX() \ | 6529 | #define _MAX() \ |
| @@ -6340,7 +6533,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6340 | e1 = POP (); \ | 6533 | e1 = POP (); \ |
| 6341 | e2 = POP (); \ | 6534 | e2 = POP (); \ |
| 6342 | \ | 6535 | \ |
| 6343 | PUSH (MAX (e1, e2)); \ | 6536 | PUSH_UNCHECKED (MAX (e1, e2)); \ |
| 6344 | } | 6537 | } |
| 6345 | 6538 | ||
| 6346 | #define _MIN() \ | 6539 | #define _MIN() \ |
| @@ -6350,7 +6543,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6350 | e1 = POP (); \ | 6543 | e1 = POP (); \ |
| 6351 | e2 = POP (); \ | 6544 | e2 = POP (); \ |
| 6352 | \ | 6545 | \ |
| 6353 | PUSH (MIN (e1, e2)); \ | 6546 | PUSH_UNCHECKED (MIN (e1, e2)); \ |
| 6354 | } | 6547 | } |
| 6355 | 6548 | ||
| 6356 | #define SCANTYPE() \ | 6549 | #define SCANTYPE() \ |
| @@ -6427,7 +6620,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6427 | result \ | 6620 | result \ |
| 6428 | = interpreter->state.round (result, \ | 6621 | = interpreter->state.round (result, \ |
| 6429 | interpreter); \ | 6622 | interpreter); \ |
| 6430 | PUSH (n < 0 ? -result : result); \ | 6623 | PUSH_UNCHECKED (n < 0 ? -result : result); \ |
| 6431 | } | 6624 | } |
| 6432 | 6625 | ||
| 6433 | #define NROUND() \ | 6626 | #define NROUND() \ |
| @@ -6435,7 +6628,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6435 | sfnt_f26dot6 n; \ | 6628 | sfnt_f26dot6 n; \ |
| 6436 | \ | 6629 | \ |
| 6437 | n = POP (); \ | 6630 | n = POP (); \ |
| 6438 | PUSH (n); \ | 6631 | PUSH_UNCHECKED (n); \ |
| 6439 | } | 6632 | } |
| 6440 | 6633 | ||
| 6441 | #define ROFF() \ | 6634 | #define ROFF() \ |
| @@ -6904,7 +7097,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6904 | else \ | 7097 | else \ |
| 6905 | value = PROJECT (x, y); \ | 7098 | value = PROJECT (x, y); \ |
| 6906 | \ | 7099 | \ |
| 6907 | PUSH (value); \ | 7100 | PUSH_UNCHECKED (value); \ |
| 6908 | } | 7101 | } |
| 6909 | 7102 | ||
| 6910 | #define SCFS() \ | 7103 | #define SCFS() \ |
| @@ -6923,14 +7116,14 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6923 | uint32_t p1, p2; \ | 7116 | uint32_t p1, p2; \ |
| 6924 | sfnt_f26dot6 distance; \ | 7117 | sfnt_f26dot6 distance; \ |
| 6925 | \ | 7118 | \ |
| 6926 | p1 = POP (); \ | ||
| 6927 | p2 = POP (); \ | 7119 | p2 = POP (); \ |
| 7120 | p1 = POP (); \ | ||
| 6928 | \ | 7121 | \ |
| 6929 | distance \ | 7122 | distance \ |
| 6930 | = sfnt_measure_distance (interpreter, \ | 7123 | = sfnt_measure_distance (interpreter, \ |
| 6931 | p1, p2, \ | 7124 | p1, p2, \ |
| 6932 | opcode); \ | 7125 | opcode); \ |
| 6933 | PUSH (distance); \ | 7126 | PUSH_UNCHECKED (distance); \ |
| 6934 | } | 7127 | } |
| 6935 | 7128 | ||
| 6936 | #define FLIPPT() \ | 7129 | #define FLIPPT() \ |
| @@ -7405,6 +7598,8 @@ sfnt_move_zp2 (struct sfnt_interpreter *interpreter, uint32_t point, | |||
| 7405 | /* Move N points from the specified POINT in INTERPRETER's glyph zone | 7598 | /* Move N points from the specified POINT in INTERPRETER's glyph zone |
| 7406 | by the given DISTANCE along the freedom vector. | 7599 | by the given DISTANCE along the freedom vector. |
| 7407 | 7600 | ||
| 7601 | Do not touch the points that are moved. | ||
| 7602 | |||
| 7408 | No checking is done to ensure that POINT lies inside the zone, or | 7603 | No checking is done to ensure that POINT lies inside the zone, or |
| 7409 | even that the zone exists at all. */ | 7604 | even that the zone exists at all. */ |
| 7410 | 7605 | ||
| @@ -7414,13 +7609,14 @@ sfnt_move_glyph_zone (struct sfnt_interpreter *interpreter, uint32_t point, | |||
| 7414 | { | 7609 | { |
| 7415 | interpreter->state.move (&interpreter->glyph_zone->x_current[point], | 7610 | interpreter->state.move (&interpreter->glyph_zone->x_current[point], |
| 7416 | &interpreter->glyph_zone->y_current[point], | 7611 | &interpreter->glyph_zone->y_current[point], |
| 7417 | n, interpreter, distance, | 7612 | n, interpreter, distance, NULL); |
| 7418 | &interpreter->glyph_zone->flags[point]); | ||
| 7419 | } | 7613 | } |
| 7420 | 7614 | ||
| 7421 | /* Move N points from the specified POINT in INTERPRETER's twilight | 7615 | /* Move N points from the specified POINT in INTERPRETER's twilight |
| 7422 | zone by the given DISTANCE along the freedom vector. | 7616 | zone by the given DISTANCE along the freedom vector. |
| 7423 | 7617 | ||
| 7618 | Do not touch the points that are moved. | ||
| 7619 | |||
| 7424 | No checking is done to ensure that POINT lies inside the zone, or | 7620 | No checking is done to ensure that POINT lies inside the zone, or |
| 7425 | even that the zone exists at all. */ | 7621 | even that the zone exists at all. */ |
| 7426 | 7622 | ||
| @@ -7436,6 +7632,8 @@ sfnt_move_twilight_zone (struct sfnt_interpreter *interpreter, uint32_t point, | |||
| 7436 | /* Move the point P in the zone pointed to by the ZP2 register in | 7632 | /* Move the point P in the zone pointed to by the ZP2 register in |
| 7437 | INTERPRETER's graphics state by DX, and DY. | 7633 | INTERPRETER's graphics state by DX, and DY. |
| 7438 | 7634 | ||
| 7635 | Touch the point P in the directions of the movement. | ||
| 7636 | |||
| 7439 | Check that P is valid; if not, trap. Else, perform the move | 7637 | Check that P is valid; if not, trap. Else, perform the move |
| 7440 | directly without converting it from the projection vector or to the | 7638 | directly without converting it from the projection vector or to the |
| 7441 | freedom vector. */ | 7639 | freedom vector. */ |
| @@ -7464,6 +7662,12 @@ sfnt_direct_move_zp2 (struct sfnt_interpreter *interpreter, uint32_t p, | |||
| 7464 | = sfnt_add (interpreter->glyph_zone->x_current[p], dx); | 7662 | = sfnt_add (interpreter->glyph_zone->x_current[p], dx); |
| 7465 | interpreter->glyph_zone->y_current[p] | 7663 | interpreter->glyph_zone->y_current[p] |
| 7466 | = sfnt_add (interpreter->glyph_zone->y_current[p], dy); | 7664 | = sfnt_add (interpreter->glyph_zone->y_current[p], dy); |
| 7665 | |||
| 7666 | if (dx) | ||
| 7667 | interpreter->glyph_zone->flags[p] |= SFNT_POINT_TOUCHED_X; | ||
| 7668 | |||
| 7669 | if (dy) | ||
| 7670 | interpreter->glyph_zone->flags[p] |= SFNT_POINT_TOUCHED_Y; | ||
| 7467 | } | 7671 | } |
| 7468 | } | 7672 | } |
| 7469 | 7673 | ||
| @@ -7578,10 +7782,8 @@ sfnt_interpret_scfs (struct sfnt_interpreter *interpreter, | |||
| 7578 | 7782 | ||
| 7579 | if (!interpreter->state.zp2) | 7783 | if (!interpreter->state.zp2) |
| 7580 | { | 7784 | { |
| 7581 | interpreter->twilight_original_x[p] | 7785 | interpreter->twilight_original_x[p] = interpreter->twilight_x[p]; |
| 7582 | = interpreter->twilight_x[p]; | 7786 | interpreter->twilight_original_y[p] = interpreter->twilight_y[p]; |
| 7583 | interpreter->twilight_original_y[p] | ||
| 7584 | = interpreter->twilight_y[p]; | ||
| 7585 | } | 7787 | } |
| 7586 | } | 7788 | } |
| 7587 | 7789 | ||
| @@ -10974,8 +11176,9 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph, | |||
| 10974 | /* Load the fword. */ | 11176 | /* Load the fword. */ |
| 10975 | tem = glyph->simple->y_coordinates[i]; | 11177 | tem = glyph->simple->y_coordinates[i]; |
| 10976 | 11178 | ||
| 10977 | /* Scale that fword. */ | 11179 | /* Scale that fword. Make sure not to round Y, as this could |
| 10978 | tem = sfnt_mul_f26dot6_fixed (tem * 64, interpreter->scale); | 11180 | lead to Y spilling over to the next line. */ |
| 11181 | tem = sfnt_mul_fixed (tem * 64, interpreter->scale); | ||
| 10979 | 11182 | ||
| 10980 | /* Set y_points and y_current. */ | 11183 | /* Set y_points and y_current. */ |
| 10981 | zone->y_points[i] = tem; | 11184 | zone->y_points[i] = tem; |
| @@ -11124,19 +11327,20 @@ static void | |||
| 11124 | sfnt_test_span (struct sfnt_edge *edge, sfnt_fixed y, | 11327 | sfnt_test_span (struct sfnt_edge *edge, sfnt_fixed y, |
| 11125 | void *dcontext) | 11328 | void *dcontext) |
| 11126 | { | 11329 | { |
| 11127 | #if 0 | 11330 | #if 1 |
| 11128 | printf ("/* span at %g */\n", sfnt_coerce_fixed (y)); | 11331 | printf ("/* span at %g */\n", sfnt_coerce_fixed (y)); |
| 11129 | for (; edge; edge = edge->next) | 11332 | for (; edge; edge = edge->next) |
| 11130 | { | 11333 | { |
| 11131 | if (y >= edge->bottom && y < edge->top) | 11334 | if (y >= edge->bottom && y < edge->top) |
| 11132 | printf ("ctx.fillRect (%g, %g, 1, 1); " | 11335 | printf ("ctx.fillRect (%g, %g, 1, 1); " |
| 11133 | "/* %g top: %g bot: %g stepx: %g */\n", | 11336 | "/* %g top: %g bot: %g stepx: %g winding: %d */\n", |
| 11134 | sfnt_coerce_fixed (edge->x), | 11337 | sfnt_coerce_fixed (edge->x), |
| 11135 | sfnt_coerce_fixed (sfnt_test_max - y), | 11338 | sfnt_coerce_fixed (sfnt_test_max - y), |
| 11136 | sfnt_coerce_fixed (y), | 11339 | sfnt_coerce_fixed (y), |
| 11137 | sfnt_coerce_fixed (edge->bottom), | 11340 | sfnt_coerce_fixed (edge->bottom), |
| 11138 | sfnt_coerce_fixed (edge->top), | 11341 | sfnt_coerce_fixed (edge->top), |
| 11139 | sfnt_coerce_fixed (edge->step_x)); | 11342 | sfnt_coerce_fixed (edge->step_x), |
| 11343 | edge->winding); | ||
| 11140 | } | 11344 | } |
| 11141 | #elif 0 | 11345 | #elif 0 |
| 11142 | int winding; | 11346 | int winding; |
| @@ -11171,6 +11375,74 @@ sfnt_test_edge_ignore (struct sfnt_edge *edges, size_t num_edges, | |||
| 11171 | 11375 | ||
| 11172 | } | 11376 | } |
| 11173 | 11377 | ||
| 11378 | /* The same debugger stuff is used here. */ | ||
| 11379 | static void sfnt_setup_debugger (void); | ||
| 11380 | |||
| 11381 | /* The debugger's X display. */ | ||
| 11382 | static Display *display; | ||
| 11383 | |||
| 11384 | /* The debugger window. */ | ||
| 11385 | static Window window; | ||
| 11386 | |||
| 11387 | /* The GC. */ | ||
| 11388 | static GC point_gc, background_gc; | ||
| 11389 | |||
| 11390 | static void | ||
| 11391 | sfnt_test_edges (struct sfnt_edge *edges, size_t num_edges) | ||
| 11392 | { | ||
| 11393 | static sfnt_fixed y; | ||
| 11394 | size_t i; | ||
| 11395 | |||
| 11396 | for (i = 0; i < num_edges; ++i) | ||
| 11397 | { | ||
| 11398 | if (y >= edges[i].bottom && y < edges[i].top) | ||
| 11399 | { | ||
| 11400 | XDrawPoint (display, window, point_gc, | ||
| 11401 | edges[i].x / 65536, 100 - (y / 65536)); | ||
| 11402 | printf ("sfnt_test_edges: %d %d\n", | ||
| 11403 | edges[i].x / 65536, 100 - (y / 65536)); | ||
| 11404 | } | ||
| 11405 | } | ||
| 11406 | |||
| 11407 | y += SFNT_POLY_STEP; | ||
| 11408 | |||
| 11409 | for (i = 0; i < num_edges; ++i) | ||
| 11410 | sfnt_step_edge (&edges[i]); | ||
| 11411 | } | ||
| 11412 | |||
| 11413 | static void | ||
| 11414 | sfnt_debug_edges (struct sfnt_edge *edges, size_t num_edges) | ||
| 11415 | { | ||
| 11416 | XEvent event; | ||
| 11417 | |||
| 11418 | sfnt_setup_debugger (); | ||
| 11419 | |||
| 11420 | while (true) | ||
| 11421 | { | ||
| 11422 | XNextEvent (display, &event); | ||
| 11423 | |||
| 11424 | switch (event.type) | ||
| 11425 | { | ||
| 11426 | case KeyPress: | ||
| 11427 | XDestroyWindow (display, window); | ||
| 11428 | XCloseDisplay (display); | ||
| 11429 | exit (0); | ||
| 11430 | break; | ||
| 11431 | |||
| 11432 | case Expose: | ||
| 11433 | |||
| 11434 | while (true) | ||
| 11435 | { | ||
| 11436 | sfnt_test_edges (edges, num_edges); | ||
| 11437 | XFlush (display); | ||
| 11438 | usleep (50000); | ||
| 11439 | } | ||
| 11440 | |||
| 11441 | break; | ||
| 11442 | } | ||
| 11443 | } | ||
| 11444 | } | ||
| 11445 | |||
| 11174 | static void | 11446 | static void |
| 11175 | sfnt_test_edge (struct sfnt_edge *edges, size_t num_edges, | 11447 | sfnt_test_edge (struct sfnt_edge *edges, size_t num_edges, |
| 11176 | void *dcontext) | 11448 | void *dcontext) |
| @@ -11182,14 +11454,13 @@ sfnt_test_edge (struct sfnt_edge *edges, size_t num_edges, | |||
| 11182 | for (i = 0; i < num_edges; ++i) | 11454 | for (i = 0; i < num_edges; ++i) |
| 11183 | { | 11455 | { |
| 11184 | printf ("/* edge x, top, bot: %g, %g - %g. winding: %d */\n" | 11456 | printf ("/* edge x, top, bot: %g, %g - %g. winding: %d */\n" |
| 11185 | "/* edge step_x: %g, source_x: %g (%d) */\n", | 11457 | "/* edge step_x: %g, sign: %d */\n", |
| 11186 | sfnt_coerce_fixed (edges[i].x), | 11458 | sfnt_coerce_fixed (edges[i].x), |
| 11187 | sfnt_coerce_fixed (edges[i].top), | 11459 | sfnt_coerce_fixed (edges[i].top), |
| 11188 | sfnt_coerce_fixed (edges[i].bottom), | 11460 | sfnt_coerce_fixed (edges[i].bottom), |
| 11189 | edges[i].winding, | 11461 | edges[i].winding, |
| 11190 | sfnt_coerce_fixed (edges[i].step_x), | 11462 | sfnt_coerce_fixed (edges[i].step_x), |
| 11191 | sfnt_coerce_fixed (edges[i].source_x), | 11463 | edges[i].signed_step); |
| 11192 | edges[i].source_x); | ||
| 11193 | #ifdef TEST_VERTEX | 11464 | #ifdef TEST_VERTEX |
| 11194 | printf ("ctx.fillRect (%g, %g, 1, 1);\n", | 11465 | printf ("ctx.fillRect (%g, %g, 1, 1);\n", |
| 11195 | sfnt_coerce_fixed (edges[i].x), | 11466 | sfnt_coerce_fixed (edges[i].x), |
| @@ -11203,12 +11474,134 @@ sfnt_test_edge (struct sfnt_edge *edges, size_t num_edges, | |||
| 11203 | #endif | 11474 | #endif |
| 11204 | } | 11475 | } |
| 11205 | 11476 | ||
| 11477 | if (getenv ("SFNT_DEBUG_STEP")) | ||
| 11478 | { | ||
| 11479 | if (!fork ()) | ||
| 11480 | sfnt_debug_edges (edges, num_edges); | ||
| 11481 | } | ||
| 11482 | |||
| 11206 | printf ("==end of edges==\n"); | 11483 | printf ("==end of edges==\n"); |
| 11207 | 11484 | ||
| 11208 | sfnt_poly_edges (edges, num_edges, sfnt_test_span, NULL); | 11485 | sfnt_poly_edges (edges, num_edges, sfnt_test_span, NULL); |
| 11209 | } | 11486 | } |
| 11210 | 11487 | ||
| 11211 | static void | 11488 | static void |
| 11489 | sfnt_x_raster (struct sfnt_raster *raster) | ||
| 11490 | { | ||
| 11491 | Display *display; | ||
| 11492 | Window window; | ||
| 11493 | Pixmap pixmap; | ||
| 11494 | Picture glyph, drawable, solid; | ||
| 11495 | int event_base, error_base; | ||
| 11496 | int major, minor, *depths, count; | ||
| 11497 | XRenderPictFormat *format, *glyph_format; | ||
| 11498 | Visual *visual; | ||
| 11499 | XImage image; | ||
| 11500 | GC gc; | ||
| 11501 | XGCValues gcvalues; | ||
| 11502 | XEvent event; | ||
| 11503 | XRenderColor white, black; | ||
| 11504 | int i; | ||
| 11505 | |||
| 11506 | display = XOpenDisplay (NULL); | ||
| 11507 | |||
| 11508 | if (!display) | ||
| 11509 | exit (0); | ||
| 11510 | |||
| 11511 | if (!XRenderQueryExtension (display, &event_base, &error_base) | ||
| 11512 | || !XRenderQueryVersion (display, &major, &minor)) | ||
| 11513 | exit (0); | ||
| 11514 | |||
| 11515 | if (major == 0 && minor < 10) | ||
| 11516 | exit (0); | ||
| 11517 | |||
| 11518 | window = XCreateSimpleWindow (display, DefaultRootWindow (display), | ||
| 11519 | 0, 0, 40, 40, 0, 0, | ||
| 11520 | WhitePixel (display, | ||
| 11521 | DefaultScreen (display))); | ||
| 11522 | XSelectInput (display, window, ExposureMask); | ||
| 11523 | XMapWindow (display, window); | ||
| 11524 | |||
| 11525 | visual = DefaultVisual (display, DefaultScreen (display)); | ||
| 11526 | format = XRenderFindVisualFormat (display, visual); | ||
| 11527 | |||
| 11528 | if (!format) | ||
| 11529 | exit (0); | ||
| 11530 | |||
| 11531 | glyph_format = XRenderFindStandardFormat (display, PictStandardA8); | ||
| 11532 | depths = XListDepths (display, DefaultScreen (display), &count); | ||
| 11533 | |||
| 11534 | for (i = 0; i < count; ++i) | ||
| 11535 | { | ||
| 11536 | if (depths[i] == 8) | ||
| 11537 | goto depth_found; | ||
| 11538 | } | ||
| 11539 | |||
| 11540 | exit (0); | ||
| 11541 | |||
| 11542 | depth_found: | ||
| 11543 | |||
| 11544 | XFree (depths); | ||
| 11545 | pixmap = XCreatePixmap (display, DefaultRootWindow (display), | ||
| 11546 | raster->width, raster->height, 8); | ||
| 11547 | |||
| 11548 | /* Upload the raster. */ | ||
| 11549 | image.width = raster->width; | ||
| 11550 | image.height = raster->height; | ||
| 11551 | image.xoffset = 0; | ||
| 11552 | image.format = ZPixmap; | ||
| 11553 | image.data = (char *) raster->cells; | ||
| 11554 | image.byte_order = MSBFirst; | ||
| 11555 | image.bitmap_unit = 8; | ||
| 11556 | image.bitmap_bit_order = LSBFirst; | ||
| 11557 | image.bitmap_pad = SFNT_POLY_ALIGNMENT * 8; | ||
| 11558 | image.depth = 8; | ||
| 11559 | image.bytes_per_line = raster->stride; | ||
| 11560 | image.bits_per_pixel = 8; | ||
| 11561 | image.red_mask = 0; | ||
| 11562 | image.green_mask = 0; | ||
| 11563 | image.blue_mask = 0; | ||
| 11564 | |||
| 11565 | if (!XInitImage (&image)) | ||
| 11566 | abort (); | ||
| 11567 | |||
| 11568 | gc = XCreateGC (display, pixmap, 0, &gcvalues); | ||
| 11569 | XPutImage (display, pixmap, gc, &image, | ||
| 11570 | 0, 0, 0, 0, image.width, image.height); | ||
| 11571 | |||
| 11572 | drawable = XRenderCreatePicture (display, window, format, | ||
| 11573 | 0, NULL); | ||
| 11574 | glyph = XRenderCreatePicture (display, pixmap, glyph_format, | ||
| 11575 | 0, NULL); | ||
| 11576 | memset (&black, 0, sizeof black); | ||
| 11577 | black.alpha = 65535; | ||
| 11578 | |||
| 11579 | solid = XRenderCreateSolidFill (display, &black); | ||
| 11580 | |||
| 11581 | while (true) | ||
| 11582 | { | ||
| 11583 | XNextEvent (display, &event); | ||
| 11584 | |||
| 11585 | if (event.type == Expose) | ||
| 11586 | { | ||
| 11587 | white.red = 65535; | ||
| 11588 | white.green = 65535; | ||
| 11589 | white.blue = 65535; | ||
| 11590 | white.alpha = 65535; | ||
| 11591 | |||
| 11592 | /* Clear the background. */ | ||
| 11593 | XRenderFillRectangle (display, PictOpSrc, drawable, | ||
| 11594 | &white, 0, 0, 65535, 65535); | ||
| 11595 | |||
| 11596 | /* Draw the solid fill with the glyph as clip mask. */ | ||
| 11597 | XRenderComposite (display, PictOpOver, solid, glyph, | ||
| 11598 | drawable, 0, 0, 0, 0, 0, 0, | ||
| 11599 | raster->width, raster->height); | ||
| 11600 | } | ||
| 11601 | } | ||
| 11602 | } | ||
| 11603 | |||
| 11604 | static void | ||
| 11212 | sfnt_test_raster (struct sfnt_raster *raster) | 11605 | sfnt_test_raster (struct sfnt_raster *raster) |
| 11213 | { | 11606 | { |
| 11214 | int x, y; | 11607 | int x, y; |
| @@ -11219,6 +11612,12 @@ sfnt_test_raster (struct sfnt_raster *raster) | |||
| 11219 | printf ("%3d ", (int) raster->cells[y * raster->stride + x]); | 11612 | printf ("%3d ", (int) raster->cells[y * raster->stride + x]); |
| 11220 | puts (""); | 11613 | puts (""); |
| 11221 | } | 11614 | } |
| 11615 | |||
| 11616 | if (getenv ("SFNT_X")) | ||
| 11617 | { | ||
| 11618 | if (!fork ()) | ||
| 11619 | sfnt_x_raster (raster); | ||
| 11620 | } | ||
| 11222 | } | 11621 | } |
| 11223 | 11622 | ||
| 11224 | 11623 | ||
| @@ -12060,7 +12459,7 @@ static struct sfnt_generic_test_args wcvtp_test_args = | |||
| 12060 | 12459 | ||
| 12061 | static struct sfnt_generic_test_args rcvt_test_args = | 12460 | static struct sfnt_generic_test_args rcvt_test_args = |
| 12062 | { | 12461 | { |
| 12063 | (uint32_t []) { 135, }, | 12462 | (uint32_t []) { 136, }, |
| 12064 | 1, | 12463 | 1, |
| 12065 | true, | 12464 | true, |
| 12066 | 5, | 12465 | 5, |
| @@ -12309,8 +12708,8 @@ static struct sfnt_generic_test_args jrof_test_args = | |||
| 12309 | 12708 | ||
| 12310 | static struct sfnt_generic_test_args deltac1_test_args = | 12709 | static struct sfnt_generic_test_args deltac1_test_args = |
| 12311 | { | 12710 | { |
| 12312 | (uint32_t []) { ((50 * 17 * 65535 / 800) >> 10) + 8, | 12711 | (uint32_t []) { ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8, |
| 12313 | ((50 * 17 * 65535 / 800) >> 10) + 8, }, | 12712 | ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8, }, |
| 12314 | 2, | 12713 | 2, |
| 12315 | false, | 12714 | false, |
| 12316 | 22, | 12715 | 22, |
| @@ -12318,8 +12717,8 @@ static struct sfnt_generic_test_args deltac1_test_args = | |||
| 12318 | 12717 | ||
| 12319 | static struct sfnt_generic_test_args deltac2_test_args = | 12718 | static struct sfnt_generic_test_args deltac2_test_args = |
| 12320 | { | 12719 | { |
| 12321 | (uint32_t []) { ((50 * 17 * 65535 / 800) >> 10) + 8, | 12720 | (uint32_t []) { ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8, |
| 12322 | ((50 * 17 * 65535 / 800) >> 10) + 8, }, | 12721 | ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8, }, |
| 12323 | 2, | 12722 | 2, |
| 12324 | false, | 12723 | false, |
| 12325 | 22, | 12724 | 22, |
| @@ -12327,8 +12726,8 @@ static struct sfnt_generic_test_args deltac2_test_args = | |||
| 12327 | 12726 | ||
| 12328 | static struct sfnt_generic_test_args deltac3_test_args = | 12727 | static struct sfnt_generic_test_args deltac3_test_args = |
| 12329 | { | 12728 | { |
| 12330 | (uint32_t []) { ((50 * 17 * 65535 / 800) >> 10) + 8, | 12729 | (uint32_t []) { ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8, |
| 12331 | ((50 * 17 * 65535 / 800) >> 10) + 8, }, | 12730 | ((((50 * 17 * 65535) + 32767) / 800) >> 10) + 8, }, |
| 12332 | 2, | 12731 | 2, |
| 12333 | false, | 12732 | false, |
| 12334 | 22, | 12733 | 22, |
| @@ -12489,8 +12888,8 @@ static struct sfnt_generic_test_args roll_test_args = | |||
| 12489 | 12888 | ||
| 12490 | static struct sfnt_generic_test_args roll_1_test_args = | 12889 | static struct sfnt_generic_test_args roll_1_test_args = |
| 12491 | { | 12890 | { |
| 12492 | (uint32_t []) { }, | 12891 | (uint32_t []) { 1, 2, }, |
| 12493 | 0, | 12892 | 2, |
| 12494 | true, | 12893 | true, |
| 12495 | 3, | 12894 | 3, |
| 12496 | }; | 12895 | }; |
| @@ -13993,15 +14392,6 @@ static struct sfnt_interpreter_test all_tests[] = | |||
| 13993 | 14392 | ||
| 13994 | /* Instruction debugger. */ | 14393 | /* Instruction debugger. */ |
| 13995 | 14394 | ||
| 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 | 14395 | static void |
| 14006 | sfnt_setup_debugger (void) | 14396 | sfnt_setup_debugger (void) |
| 14007 | { | 14397 | { |
| @@ -14383,6 +14773,13 @@ sfnt_run_hook (struct sfnt_interpreter *interpreter) | |||
| 14383 | pid_t pid; | 14773 | pid_t pid; |
| 14384 | XEvent event; | 14774 | XEvent event; |
| 14385 | 14775 | ||
| 14776 | #ifdef TEST_BREAK_AFTER | ||
| 14777 | static unsigned int instructions; | ||
| 14778 | |||
| 14779 | if (++instructions < TEST_BREAK_AFTER) | ||
| 14780 | return; | ||
| 14781 | #endif | ||
| 14782 | |||
| 14386 | pid = fork (); | 14783 | pid = fork (); |
| 14387 | 14784 | ||
| 14388 | if (pid == 0) | 14785 | if (pid == 0) |
| @@ -14414,6 +14811,41 @@ sfnt_run_hook (struct sfnt_interpreter *interpreter) | |||
| 14414 | } | 14811 | } |
| 14415 | } | 14812 | } |
| 14416 | 14813 | ||
| 14814 | static struct sfnt_prep_table *exec_prep; | ||
| 14815 | static struct sfnt_fpgm_table *exec_fpgm; | ||
| 14816 | |||
| 14817 | static const char * | ||
| 14818 | sfnt_identify_instruction (struct sfnt_interpreter *interpreter) | ||
| 14819 | { | ||
| 14820 | static char buffer[256]; | ||
| 14821 | unsigned char *where; | ||
| 14822 | |||
| 14823 | where = interpreter->instructions + interpreter->IP; | ||
| 14824 | |||
| 14825 | if (exec_prep | ||
| 14826 | && where >= exec_prep->instructions | ||
| 14827 | && where < (exec_prep->instructions | ||
| 14828 | + exec_prep->num_instructions)) | ||
| 14829 | { | ||
| 14830 | sprintf (buffer, "prep+%td", | ||
| 14831 | where - exec_prep->instructions); | ||
| 14832 | return buffer; | ||
| 14833 | } | ||
| 14834 | |||
| 14835 | if (exec_fpgm->instructions | ||
| 14836 | && where >= exec_fpgm->instructions | ||
| 14837 | && where < (exec_fpgm->instructions | ||
| 14838 | + exec_fpgm->num_instructions)) | ||
| 14839 | { | ||
| 14840 | sprintf (buffer, "fpgm+%td", | ||
| 14841 | where - exec_fpgm->instructions); | ||
| 14842 | return buffer; | ||
| 14843 | } | ||
| 14844 | |||
| 14845 | sprintf (buffer, "IP+%td", where - interpreter->instructions); | ||
| 14846 | return buffer; | ||
| 14847 | } | ||
| 14848 | |||
| 14417 | static void | 14849 | static void |
| 14418 | sfnt_verbose (struct sfnt_interpreter *interpreter) | 14850 | sfnt_verbose (struct sfnt_interpreter *interpreter) |
| 14419 | { | 14851 | { |
| @@ -14421,6 +14853,8 @@ sfnt_verbose (struct sfnt_interpreter *interpreter) | |||
| 14421 | struct sfnt_glyph_outline *outline; | 14853 | struct sfnt_glyph_outline *outline; |
| 14422 | struct sfnt_raster *raster; | 14854 | struct sfnt_raster *raster; |
| 14423 | unsigned char opcode; | 14855 | unsigned char opcode; |
| 14856 | const char *name; | ||
| 14857 | static unsigned int instructions; | ||
| 14424 | 14858 | ||
| 14425 | /* Build a temporary outline containing the values of the | 14859 | /* Build a temporary outline containing the values of the |
| 14426 | interpreter's glyph zone. */ | 14860 | interpreter's glyph zone. */ |
| @@ -14444,7 +14878,43 @@ sfnt_verbose (struct sfnt_interpreter *interpreter) | |||
| 14444 | xfree (raster); | 14878 | xfree (raster); |
| 14445 | 14879 | ||
| 14446 | opcode = interpreter->instructions[interpreter->IP]; | 14880 | opcode = interpreter->instructions[interpreter->IP]; |
| 14447 | printf ("opcode: %s\n", sfnt_name_instruction (opcode)); | 14881 | printf ("opcode, number of instructions: %s %u\n", |
| 14882 | sfnt_name_instruction (opcode), instructions++); | ||
| 14883 | printf ("instruction: %s\n", | ||
| 14884 | sfnt_identify_instruction (interpreter)); | ||
| 14885 | |||
| 14886 | if (interpreter->state.project | ||
| 14887 | == sfnt_project_onto_x_axis_vector) | ||
| 14888 | name = "X axis"; | ||
| 14889 | else if (interpreter->state.project | ||
| 14890 | == sfnt_project_onto_y_axis_vector) | ||
| 14891 | name = "Y axis"; | ||
| 14892 | else | ||
| 14893 | name = "Any"; | ||
| 14894 | |||
| 14895 | printf ("projection function: %s\n", name); | ||
| 14896 | } | ||
| 14897 | |||
| 14898 | static void | ||
| 14899 | sfnt_push_hook (struct sfnt_interpreter *interpreter, | ||
| 14900 | uint32_t value) | ||
| 14901 | { | ||
| 14902 | int32_t alternate; | ||
| 14903 | |||
| 14904 | alternate = value; | ||
| 14905 | |||
| 14906 | fprintf (stderr, "--> %"PRIi32"\n", alternate); | ||
| 14907 | } | ||
| 14908 | |||
| 14909 | static void | ||
| 14910 | sfnt_pop_hook (struct sfnt_interpreter *interpreter, | ||
| 14911 | uint32_t value) | ||
| 14912 | { | ||
| 14913 | int32_t alternate; | ||
| 14914 | |||
| 14915 | alternate = value; | ||
| 14916 | |||
| 14917 | fprintf (stderr, "<<- %"PRIi32"\n", alternate); | ||
| 14448 | } | 14918 | } |
| 14449 | 14919 | ||
| 14450 | 14920 | ||
| @@ -14473,7 +14943,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter) | |||
| 14473 | -Wno-missing-field-initializers -Wno-override-init | 14943 | -Wno-missing-field-initializers -Wno-override-init |
| 14474 | -Wno-sign-compare -Wno-type-limits -Wno-unused-parameter | 14944 | -Wno-sign-compare -Wno-type-limits -Wno-unused-parameter |
| 14475 | -Wno-format-nonliteral -Wno-bidi-chars -g3 -O0 -DTEST sfnt.c -o | 14945 | -Wno-format-nonliteral -Wno-bidi-chars -g3 -O0 -DTEST sfnt.c -o |
| 14476 | sfnt ../lib/libgnu.a -lX11 | 14946 | sfnt ../lib/libgnu.a -lX11 -lXrender |
| 14477 | 14947 | ||
| 14478 | after gnulib has been built. Then, run ./sfnt | 14948 | after gnulib has been built. Then, run ./sfnt |
| 14479 | /path/to/font.ttf. */ | 14949 | /path/to/font.ttf. */ |
| @@ -14496,7 +14966,7 @@ main (int argc, char **argv) | |||
| 14496 | sfnt_glyph code; | 14966 | sfnt_glyph code; |
| 14497 | struct sfnt_test_dcontext dcontext; | 14967 | struct sfnt_test_dcontext dcontext; |
| 14498 | struct sfnt_glyph_outline *outline; | 14968 | struct sfnt_glyph_outline *outline; |
| 14499 | struct timespec start, end, sub, sub1, sub2; | 14969 | struct timespec start, end, sub, sub1, sub2, sub3; |
| 14500 | static struct sfnt_maxp_table *maxp; | 14970 | static struct sfnt_maxp_table *maxp; |
| 14501 | struct sfnt_raster *raster; | 14971 | struct sfnt_raster *raster; |
| 14502 | struct sfnt_hmtx_table *hmtx; | 14972 | struct sfnt_hmtx_table *hmtx; |
| @@ -14613,6 +15083,9 @@ main (int argc, char **argv) | |||
| 14613 | prep = sfnt_read_prep_table (fd, font); | 15083 | prep = sfnt_read_prep_table (fd, font); |
| 14614 | hmtx = NULL; | 15084 | hmtx = NULL; |
| 14615 | 15085 | ||
| 15086 | exec_prep = prep; | ||
| 15087 | exec_fpgm = fpgm; | ||
| 15088 | |||
| 14616 | if (head && maxp && maxp->version >= 0x00010000) | 15089 | if (head && maxp && maxp->version >= 0x00010000) |
| 14617 | { | 15090 | { |
| 14618 | fprintf (stderr, "creating interpreter\n" | 15091 | fprintf (stderr, "creating interpreter\n" |
| @@ -14696,7 +15169,7 @@ main (int argc, char **argv) | |||
| 14696 | "checksum_adjustment: \t\t%"PRIu32"\n" | 15169 | "checksum_adjustment: \t\t%"PRIu32"\n" |
| 14697 | "magic: \t\t\t\t%"PRIx32"\n" | 15170 | "magic: \t\t\t\t%"PRIx32"\n" |
| 14698 | "flags: \t\t\t\t%"PRIx16"\n" | 15171 | "flags: \t\t\t\t%"PRIx16"\n" |
| 14699 | "units_per_em: \t\t\t%"PRIx16"\n" | 15172 | "units_per_em: \t\t\t%"PRIu16"\n" |
| 14700 | "xmin, ymin, xmax, ymax: \t%d, %d, %d, %d\n" | 15173 | "xmin, ymin, xmax, ymax: \t%d, %d, %d, %d\n" |
| 14701 | "mac_style: \t\t\t%"PRIx16"\n" | 15174 | "mac_style: \t\t\t%"PRIx16"\n" |
| 14702 | "lowest_rec_ppem: \t\t%"PRIu16"\n" | 15175 | "lowest_rec_ppem: \t\t%"PRIu16"\n" |
| @@ -14848,7 +15321,7 @@ main (int argc, char **argv) | |||
| 14848 | 15321 | ||
| 14849 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); | 15322 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); |
| 14850 | 15323 | ||
| 14851 | for (i = 0; i < 400; ++i) | 15324 | for (i = 0; i < 1; ++i) |
| 14852 | { | 15325 | { |
| 14853 | xfree (raster); | 15326 | xfree (raster); |
| 14854 | raster = sfnt_raster_glyph_outline (outline); | 15327 | raster = sfnt_raster_glyph_outline (outline); |
| @@ -14886,7 +15359,11 @@ main (int argc, char **argv) | |||
| 14886 | if (getenv ("SFNT_DEBUG")) | 15359 | if (getenv ("SFNT_DEBUG")) |
| 14887 | interpreter->run_hook = sfnt_run_hook; | 15360 | interpreter->run_hook = sfnt_run_hook; |
| 14888 | else if (getenv ("SFNT_VERBOSE")) | 15361 | else if (getenv ("SFNT_VERBOSE")) |
| 14889 | interpreter->run_hook = sfnt_verbose; | 15362 | { |
| 15363 | interpreter->run_hook = sfnt_verbose; | ||
| 15364 | interpreter->push_hook = sfnt_push_hook; | ||
| 15365 | interpreter->pop_hook = sfnt_pop_hook; | ||
| 15366 | } | ||
| 14890 | 15367 | ||
| 14891 | if (glyph->simple | 15368 | if (glyph->simple |
| 14892 | && sfnt_lookup_glyph_metrics (code, -1, | 15369 | && sfnt_lookup_glyph_metrics (code, -1, |
| @@ -14896,8 +15373,11 @@ main (int argc, char **argv) | |||
| 14896 | { | 15373 | { |
| 14897 | printf ("interpreting glyph\n"); | 15374 | printf ("interpreting glyph\n"); |
| 14898 | interpreter->state = state; | 15375 | interpreter->state = state; |
| 15376 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); | ||
| 14899 | trap = sfnt_interpret_simple_glyph (glyph, interpreter, | 15377 | trap = sfnt_interpret_simple_glyph (glyph, interpreter, |
| 14900 | &metrics, &value); | 15378 | &metrics, &value); |
| 15379 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &end); | ||
| 15380 | sub3 = timespec_sub (end, start); | ||
| 14901 | 15381 | ||
| 14902 | if (trap) | 15382 | if (trap) |
| 14903 | printf ("**TRAP**: %s\n", trap); | 15383 | printf ("**TRAP**: %s\n", trap); |
| @@ -14920,6 +15400,9 @@ main (int argc, char **argv) | |||
| 14920 | } | 15400 | } |
| 14921 | } | 15401 | } |
| 14922 | } | 15402 | } |
| 15403 | |||
| 15404 | fprintf (stderr, "execution time: %lld sec %ld nsec\n", | ||
| 15405 | (long long) sub3.tv_sec, sub3.tv_nsec); | ||
| 14923 | } | 15406 | } |
| 14924 | 15407 | ||
| 14925 | interpreter->run_hook = NULL; | 15408 | interpreter->run_hook = NULL; |
| @@ -14931,7 +15414,7 @@ main (int argc, char **argv) | |||
| 14931 | printf ("time spent building edges: %lld sec %ld nsec\n", | 15414 | printf ("time spent building edges: %lld sec %ld nsec\n", |
| 14932 | (long long) sub1.tv_sec, sub1.tv_nsec); | 15415 | (long long) sub1.tv_sec, sub1.tv_nsec); |
| 14933 | printf ("time spent rasterizing: %lld sec %ld nsec\n", | 15416 | printf ("time spent rasterizing: %lld sec %ld nsec\n", |
| 14934 | (long long) sub2.tv_sec / 400, sub2.tv_nsec / 400); | 15417 | (long long) sub2.tv_sec / 1, sub2.tv_nsec / 1); |
| 14935 | 15418 | ||
| 14936 | xfree (outline); | 15419 | xfree (outline); |
| 14937 | } | 15420 | } |
diff --git a/src/sfnt.h b/src/sfnt.h index baed1d257dd..48522960043 100644 --- a/src/sfnt.h +++ b/src/sfnt.h | |||
| @@ -698,6 +698,13 @@ struct sfnt_raster | |||
| 698 | unsigned short refcount; | 698 | unsigned short refcount; |
| 699 | }; | 699 | }; |
| 700 | 700 | ||
| 701 | /* Bresenham's algorithm. | ||
| 702 | This rasterizer uses Bresenham's algorithm, with the minor | ||
| 703 | detail being that it does not use device pixels, but rather | ||
| 704 | pixels in a sample grid defined by SFNT_POLY_SHIFT, which is | ||
| 705 | normally set to 4x oversampling. See sfnt_poly_edges for | ||
| 706 | an explanation of how Bresenham's algorithm works. */ | ||
| 707 | |||
| 701 | struct sfnt_edge | 708 | struct sfnt_edge |
| 702 | { | 709 | { |
| 703 | /* Next edge in this chain. */ | 710 | /* Next edge in this chain. */ |
| @@ -709,15 +716,14 @@ struct sfnt_edge | |||
| 709 | /* X position, top and bottom of edges. */ | 716 | /* X position, top and bottom of edges. */ |
| 710 | sfnt_fixed x, top, bottom; | 717 | sfnt_fixed x, top, bottom; |
| 711 | 718 | ||
| 712 | /* step_x is how many pixels to move for each increase in Y by | 719 | /* Slope error. */ |
| 713 | SFNT_POLY_STEP. */ | ||
| 714 | sfnt_fixed step_x; | 720 | sfnt_fixed step_x; |
| 715 | 721 | ||
| 716 | #ifdef TEST | 722 | /* SFNT_POLY_STEP times the direction of movement. */ |
| 717 | /* Value of x before initial adjustment of bottom to match the | 723 | sfnt_fixed signed_step; |
| 718 | grid. */ | 724 | |
| 719 | sfnt_fixed source_x; | 725 | /* Slope error accumulator. */ |
| 720 | #endif | 726 | sfnt_fixed error; |
| 721 | }; | 727 | }; |
| 722 | 728 | ||
| 723 | 729 | ||
| @@ -731,7 +737,6 @@ enum | |||
| 731 | SFNT_POLY_MASK = (SFNT_POLY_SAMPLE - 1), | 737 | SFNT_POLY_MASK = (SFNT_POLY_SAMPLE - 1), |
| 732 | SFNT_POLY_STEP = (0x10000 >> SFNT_POLY_SHIFT), | 738 | SFNT_POLY_STEP = (0x10000 >> SFNT_POLY_SHIFT), |
| 733 | SFNT_POLY_START = (SFNT_POLY_STEP >> 1), | 739 | SFNT_POLY_START = (SFNT_POLY_STEP >> 1), |
| 734 | SFNT_POLY_ROUND = ((1 << (16 - SFNT_POLY_SHIFT)) / 2) - 1, | ||
| 735 | }; | 740 | }; |
| 736 | 741 | ||
| 737 | 742 | ||