diff options
| author | Po Lu | 2023-02-08 16:34:29 +0800 |
|---|---|---|
| committer | Po Lu | 2023-02-08 16:34:29 +0800 |
| commit | 1a70941c8ed58e5b78fec406f30457765f38daef (patch) | |
| tree | 7c83a40723a579688f7817d4d12581337220d21b /src | |
| parent | bd55cca4b8c8b9ff5dd0413716eb51181b9baae8 (diff) | |
| download | emacs-1a70941c8ed58e5b78fec406f30457765f38daef.tar.gz emacs-1a70941c8ed58e5b78fec406f30457765f38daef.zip | |
Improve text display on Android port
* src/sfnt.c (sfnt_build_glyph_outline): Clear
build_outline_context.
(sfnt_poly_coverage): Extend coverage map.
(sfnt_prepare_raster): Always floor coordinates, since the
increase in coverage makes this hack unnecessary.
(sfnt_build_outline_edges): Likewise.
(sfnt_compare_edges): Remove function.
(sfnt_edge_sort): New function. Since edges are already
partially sorted, and there are not many, insertion sort
suffices.
(sfnt_poly_edges): Use sfnt_edge_sort.
(sfnt_fill_span): Stop rounding x0 and x1 to the grid, and make
coverage computation static.
(sfnt_lookup_glyph_metrics): Fix return code for unscaled
metrics.
(sfnt_scale_metrics): New function.
(SFNT_ENABLE_HINTING): Remove define.
(struct sfnt_cvt_table, struct sfnt_fpgm_table)
(struct sfnt_prep_table): Move to sfnt.h.
(sfnt_read_cvt_table):
(sfnt_read_fpgm_table, sfnt_read_prep_table): Make TEST_STATIC.
(struct sfnt_unit_vector, struct sfnt_interpreter_definition)
(struct sfnt_interpreter_zone, struct sfnt_graphics_state):
(struct sfnt_interpreter): Move to sfnt.h.
(sfnt_make_interpreter): Make TEST_STATIC.
(POP, PUSH, DELTAP1, DELTAP2, DELTAP3): When TEST, define to
regular push and pop.
(sfnt_deltac):
(sfnt_deltap): Fix order of arguments.
(IUP_SINGLE_PAIR): Fix interpolation loop wraparound.
(sfnt_interpret_font_program):
(sfnt_interpret_control_value_program): Make TEST_STATIC.
(struct sfnt_instructed_outline): Move to sfnt.h.
(sfnt_build_instructed_outline): Make TEST_STATIC.
(sfnt_interpret_simple_glyph):
(sfnt_x_raster):
(sfnt_test_raster):
(all_tests):
(sfnt_verbose):
(main): Improve test code.
* src/sfnt.h (SFNT_ENABLE_HINTING, struct sfnt_cvt_table)
(struct sfnt_fpgm_table, struct sfnt_prep_table)
(struct sfnt_unit_vector, struct sfnt_interpreter_definition)
(struct sfnt_interpreter_zone, struct sfnt_graphics_state)
(struct sfnt_interpreter, struct sfnt_instructed_outline)
(PROTOTYPE): New definitions.
* src/sfntfont-android.c (sfntfont_android_put_glyphs): Make
coordinate generation more straightforward.
* src/sfntfont.c (sfntfont_get_glyph_outline): New arguments
INTERPRETER and METRICS.
(struct sfnt_font_info): New tables.
(sfntfont_setup_interpreter): New function.
(sfntfont_open): Avoid memory leak. Set up interpreter.
(sfntfont_measure_instructed_pcm): New function.
(sfntfont_measure_pcm): Delegate to measure_instructed_pcm where
appropriate.
(sfntfont_close): Free new tables.
(sfntfont_draw): Scale metrics properly.
Diffstat (limited to 'src')
| -rw-r--r-- | src/sfnt.c | 913 | ||||
| -rw-r--r-- | src/sfnt.h | 483 | ||||
| -rw-r--r-- | src/sfntfont-android.c | 4 | ||||
| -rw-r--r-- | src/sfntfont.c | 238 |
4 files changed, 1078 insertions, 560 deletions
diff --git a/src/sfnt.c b/src/sfnt.c index ab21c41b8a0..8dc189919b7 100644 --- a/src/sfnt.c +++ b/src/sfnt.c | |||
| @@ -3459,6 +3459,8 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph, | |||
| 3459 | struct sfnt_glyph_outline *outline; | 3459 | struct sfnt_glyph_outline *outline; |
| 3460 | int rc; | 3460 | int rc; |
| 3461 | 3461 | ||
| 3462 | memset (&build_outline_context, 0, sizeof build_outline_context); | ||
| 3463 | |||
| 3462 | /* Allocate the outline now with enough for 44 words at the end. */ | 3464 | /* Allocate the outline now with enough for 44 words at the end. */ |
| 3463 | outline = xmalloc (sizeof *outline + 40 * sizeof (*outline->outline)); | 3465 | outline = xmalloc (sizeof *outline + 40 * sizeof (*outline->outline)); |
| 3464 | outline->outline_size = 40; | 3466 | outline->outline_size = 40; |
| @@ -3521,12 +3523,16 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph, | |||
| 3521 | /* Coverage table. This is a four dimensional array indiced by the Y, | 3523 | /* Coverage table. This is a four dimensional array indiced by the Y, |
| 3522 | then X axis fractional, shifted down to 2 bits. */ | 3524 | then X axis fractional, shifted down to 2 bits. */ |
| 3523 | 3525 | ||
| 3524 | static unsigned char sfnt_poly_coverage[4][4] = | 3526 | static const unsigned char sfnt_poly_coverage[8][9] = |
| 3525 | { | 3527 | { |
| 3526 | { 0x10, 0x10, 0x10, 0x10 }, | 3528 | { 0, 4, 8, 12, 16, 20, 24, 28, 32, }, |
| 3527 | { 0x10, 0x10, 0x10, 0x10 }, | 3529 | { 0, 4, 8, 12, 16, 20, 24, 28, 32, }, |
| 3528 | { 0x0f, 0x10, 0x10, 0x10 }, | 3530 | { 0, 4, 8, 12, 16, 20, 24, 28, 32, }, |
| 3529 | { 0x10, 0x10, 0x10, 0x10 }, | 3531 | { 0, 3, 7, 11, 15, 19, 23, 27, 31, }, |
| 3532 | { 0, 4, 8, 12, 16, 20, 24, 28, 32, }, | ||
| 3533 | { 0, 4, 8, 12, 16, 20, 24, 28, 32, }, | ||
| 3534 | { 0, 4, 8, 12, 16, 20, 24, 28, 32, }, | ||
| 3535 | { 0, 4, 8, 12, 16, 20, 24, 28, 32, }, | ||
| 3530 | }; | 3536 | }; |
| 3531 | 3537 | ||
| 3532 | /* Return the nearest coordinate on the sample grid no less than | 3538 | /* Return the nearest coordinate on the sample grid no less than |
| @@ -3566,7 +3572,7 @@ sfnt_prepare_raster (struct sfnt_raster *raster, | |||
| 3566 | + (SFNT_POLY_ALIGNMENT - 1)) | 3572 | + (SFNT_POLY_ALIGNMENT - 1)) |
| 3567 | & ~(SFNT_POLY_ALIGNMENT - 1)); | 3573 | & ~(SFNT_POLY_ALIGNMENT - 1)); |
| 3568 | 3574 | ||
| 3569 | raster->offx = sfnt_round_fixed (outline->xmin) >> 16; | 3575 | raster->offx = sfnt_floor_fixed (outline->xmin) >> 16; |
| 3570 | raster->offy = sfnt_floor_fixed (outline->ymin) >> 16; | 3576 | raster->offy = sfnt_floor_fixed (outline->ymin) >> 16; |
| 3571 | } | 3577 | } |
| 3572 | 3578 | ||
| @@ -3602,10 +3608,9 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline, | |||
| 3602 | edge = 0; | 3608 | edge = 0; |
| 3603 | 3609 | ||
| 3604 | /* ymin and xmin must be the same as the offset used to set offy and | 3610 | /* ymin and xmin must be the same as the offset used to set offy and |
| 3605 | offx in rasters. However, xmin is not floored; otherwise, glyphs | 3611 | offx in rasters. */ |
| 3606 | like ``e'' look bad at certain ppem. */ | ||
| 3607 | ymin = sfnt_floor_fixed (outline->ymin); | 3612 | ymin = sfnt_floor_fixed (outline->ymin); |
| 3608 | xmin = outline->xmin; | 3613 | xmin = sfnt_floor_fixed (outline->xmin); |
| 3609 | 3614 | ||
| 3610 | for (i = 0; i < outline->outline_used; ++i) | 3615 | for (i = 0; i < outline->outline_used; ++i) |
| 3611 | { | 3616 | { |
| @@ -3694,15 +3699,31 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline, | |||
| 3694 | edge_proc (edges, edge, dcontext); | 3699 | edge_proc (edges, edge, dcontext); |
| 3695 | } | 3700 | } |
| 3696 | 3701 | ||
| 3697 | static int | 3702 | /* Sort an array of SIZE edges to increase by bottom Y position, in |
| 3698 | sfnt_compare_edges (const void *a, const void *b) | 3703 | preparation for building spans. |
| 3704 | |||
| 3705 | Insertion sort is used because there are usually not very many | ||
| 3706 | edges, and anything larger would bloat up the code. */ | ||
| 3707 | |||
| 3708 | static void | ||
| 3709 | sfnt_edge_sort (struct sfnt_edge *edges, size_t size) | ||
| 3699 | { | 3710 | { |
| 3700 | const struct sfnt_edge *first, *second; | 3711 | ssize_t i, j; |
| 3712 | struct sfnt_edge edge; | ||
| 3701 | 3713 | ||
| 3702 | first = a; | 3714 | for (i = 1; i < size; ++i) |
| 3703 | second = b; | 3715 | { |
| 3716 | edge = edges[i]; | ||
| 3717 | j = i - 1; | ||
| 3718 | |||
| 3719 | while (j >= 0 && (edges[j].bottom > edge.bottom)) | ||
| 3720 | { | ||
| 3721 | edges[j + 1] = edges[j]; | ||
| 3722 | j--; | ||
| 3723 | } | ||
| 3704 | 3724 | ||
| 3705 | return (int) (first->bottom - second->bottom); | 3725 | edges[j + 1] = edge; |
| 3726 | } | ||
| 3706 | } | 3727 | } |
| 3707 | 3728 | ||
| 3708 | /* Draw EDGES, an unsorted array of polygon edges of size SIZE. For | 3729 | /* Draw EDGES, an unsorted array of polygon edges of size SIZE. For |
| @@ -3751,7 +3772,7 @@ sfnt_poly_edges (struct sfnt_edge *edges, size_t size, | |||
| 3751 | 3772 | ||
| 3752 | /* Sort edges to ascend by Y-order. Once again, remember: cartesian | 3773 | /* Sort edges to ascend by Y-order. Once again, remember: cartesian |
| 3753 | coordinates. */ | 3774 | coordinates. */ |
| 3754 | qsort (edges, size, sizeof *edges, sfnt_compare_edges); | 3775 | sfnt_edge_sort (edges, size); |
| 3755 | 3776 | ||
| 3756 | /* Step down line by line. Find active edges. */ | 3777 | /* Step down line by line. Find active edges. */ |
| 3757 | 3778 | ||
| @@ -3837,10 +3858,10 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, | |||
| 3837 | sfnt_fixed x0, sfnt_fixed x1) | 3858 | sfnt_fixed x0, sfnt_fixed x1) |
| 3838 | { | 3859 | { |
| 3839 | unsigned char *start; | 3860 | unsigned char *start; |
| 3840 | unsigned char *coverage; | 3861 | const unsigned char *coverage; |
| 3841 | sfnt_fixed left, right, end; | 3862 | sfnt_fixed left, right, end; |
| 3842 | unsigned short w, a; | 3863 | unsigned short w, a; |
| 3843 | int row, col; | 3864 | int row; |
| 3844 | 3865 | ||
| 3845 | /* Clip bounds to pixmap. */ | 3866 | /* Clip bounds to pixmap. */ |
| 3846 | if (x0 < 0) | 3867 | if (x0 < 0) |
| @@ -3863,16 +3884,10 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, | |||
| 3863 | return; | 3884 | return; |
| 3864 | 3885 | ||
| 3865 | /* Set start, then start filling according to coverage. left and | 3886 | /* Set start, then start filling according to coverage. left and |
| 3866 | right are now 16.2. */ | 3887 | right are now .3. */ |
| 3867 | left = sfnt_poly_grid_ceil (x0) >> (16 - SFNT_POLY_SHIFT); | 3888 | left = x0 >> (16 - SFNT_POLY_SHIFT); |
| 3868 | right = sfnt_poly_grid_ceil (x1) >> (16 - SFNT_POLY_SHIFT); | 3889 | right = x1 >> (16 - SFNT_POLY_SHIFT); |
| 3869 | #if 7 > __GNUC__ | ||
| 3870 | start = raster->cells + row * raster->stride; | 3890 | start = raster->cells + row * raster->stride; |
| 3871 | #else | ||
| 3872 | start = __builtin_assume_aligned ((raster->cells | ||
| 3873 | + row * raster->stride), | ||
| 3874 | SFNT_POLY_ALIGNMENT); | ||
| 3875 | #endif | ||
| 3876 | start += left >> SFNT_POLY_SHIFT; | 3891 | start += left >> SFNT_POLY_SHIFT; |
| 3877 | 3892 | ||
| 3878 | w = 0; | 3893 | w = 0; |
| @@ -3880,25 +3895,25 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, | |||
| 3880 | /* Compute coverage for first pixel, then poly. */ | 3895 | /* Compute coverage for first pixel, then poly. */ |
| 3881 | if (left & SFNT_POLY_MASK) | 3896 | if (left & SFNT_POLY_MASK) |
| 3882 | { | 3897 | { |
| 3883 | /* Note that col is an index into the columns of the coverage | 3898 | /* Compute the coverage for the first pixel, and move left past |
| 3884 | map, unlike row which indexes the raster. */ | 3899 | it. The coverage is a number from 1 to 7 describing how |
| 3885 | col = 0; | 3900 | ``partially'' covered this pixel is. */ |
| 3886 | |||
| 3887 | /* Precompute this to allow for better optimizations. */ | ||
| 3888 | end = ((left + SFNT_POLY_SAMPLE - 1) & ~SFNT_POLY_MASK); | ||
| 3889 | 3901 | ||
| 3890 | while (left < right && left < end) | 3902 | end = (left + SFNT_POLY_SAMPLE - 1) & ~SFNT_POLY_MASK; |
| 3891 | left++, w += coverage[col++]; | 3903 | end = MIN (right, end); |
| 3892 | 3904 | ||
| 3905 | w = coverage[end - left]; | ||
| 3893 | a = *start + w; | 3906 | a = *start + w; |
| 3907 | |||
| 3908 | /* Now move left past. */ | ||
| 3909 | left = end; | ||
| 3910 | |||
| 3894 | *start++ = sfnt_saturate_short (a); | 3911 | *start++ = sfnt_saturate_short (a); |
| 3895 | } | 3912 | } |
| 3896 | 3913 | ||
| 3897 | /* Clear coverage info for first pixel. Compute coverage for center | 3914 | /* Clear coverage info for first pixel. Compute coverage for center |
| 3898 | pixels. */ | 3915 | pixels. */ |
| 3899 | w = 0; | 3916 | w = coverage[SFNT_POLY_MASK]; |
| 3900 | for (col = 0; col < SFNT_POLY_SAMPLE; ++col) | ||
| 3901 | w += coverage[col]; | ||
| 3902 | 3917 | ||
| 3903 | /* Fill pixels between left and right. */ | 3918 | /* Fill pixels between left and right. */ |
| 3904 | while (left + SFNT_POLY_MASK < right) | 3919 | while (left + SFNT_POLY_MASK < right) |
| @@ -3912,10 +3927,7 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, | |||
| 3912 | part.) */ | 3927 | part.) */ |
| 3913 | if (right & SFNT_POLY_MASK) | 3928 | if (right & SFNT_POLY_MASK) |
| 3914 | { | 3929 | { |
| 3915 | w = 0; | 3930 | w = coverage[right - left]; |
| 3916 | col = 0; | ||
| 3917 | while (left < right) | ||
| 3918 | left++, w += coverage[col++]; | ||
| 3919 | a = *start + w; | 3931 | a = *start + w; |
| 3920 | *start = sfnt_saturate_short (a); | 3932 | *start = sfnt_saturate_short (a); |
| 3921 | } | 3933 | } |
| @@ -4155,20 +4167,34 @@ sfnt_lookup_glyph_metrics (sfnt_glyph glyph, int pixel_size, | |||
| 4155 | /* Return unscaled metrics in this case. */ | 4167 | /* Return unscaled metrics in this case. */ |
| 4156 | metrics->lbearing = lbearing; | 4168 | metrics->lbearing = lbearing; |
| 4157 | metrics->advance = advance; | 4169 | metrics->advance = advance; |
| 4158 | return 1; | 4170 | return 0; |
| 4159 | } | 4171 | } |
| 4160 | 4172 | ||
| 4161 | /* Now scale lbearing and advance up to the pixel size. */ | 4173 | /* Now scale lbearing and advance up to the pixel size. */ |
| 4162 | factor = sfnt_div_fixed (pixel_size, head->units_per_em); | 4174 | factor = sfnt_div_fixed (pixel_size, head->units_per_em); |
| 4163 | 4175 | ||
| 4164 | /* Save them. */ | 4176 | /* Save them. */ |
| 4165 | metrics->lbearing = sfnt_mul_fixed (lbearing << 16, factor); | 4177 | metrics->lbearing = sfnt_mul_fixed (lbearing * 65536, factor); |
| 4166 | metrics->advance = sfnt_mul_fixed (advance << 16, factor); | 4178 | metrics->advance = sfnt_mul_fixed (advance * 65536, factor); |
| 4167 | 4179 | ||
| 4168 | /* All done. */ | 4180 | /* All done. */ |
| 4169 | return 0; | 4181 | return 0; |
| 4170 | } | 4182 | } |
| 4171 | 4183 | ||
| 4184 | /* Scale the specified glyph metrics by FACTOR. | ||
| 4185 | Set METRICS->lbearing and METRICS->advance to their current | ||
| 4186 | values times factor. */ | ||
| 4187 | |||
| 4188 | MAYBE_UNUSED TEST_STATIC void | ||
| 4189 | sfnt_scale_metrics (struct sfnt_glyph_metrics *metrics, | ||
| 4190 | sfnt_fixed factor) | ||
| 4191 | { | ||
| 4192 | metrics->lbearing | ||
| 4193 | = sfnt_mul_fixed (metrics->lbearing * 65536, factor); | ||
| 4194 | metrics->advance | ||
| 4195 | = sfnt_mul_fixed (metrics->advance * 65536, factor); | ||
| 4196 | } | ||
| 4197 | |||
| 4172 | 4198 | ||
| 4173 | 4199 | ||
| 4174 | /* Font style parsing. */ | 4200 | /* Font style parsing. */ |
| @@ -4602,10 +4628,6 @@ sfnt_read_ttc_header (int fd) | |||
| 4602 | 4628 | ||
| 4603 | 4629 | ||
| 4604 | 4630 | ||
| 4605 | #ifdef TEST | ||
| 4606 | #define SFNT_ENABLE_HINTING | ||
| 4607 | #endif | ||
| 4608 | |||
| 4609 | #ifdef SFNT_ENABLE_HINTING | 4631 | #ifdef SFNT_ENABLE_HINTING |
| 4610 | 4632 | ||
| 4611 | /* TrueType hinting support. | 4633 | /* TrueType hinting support. |
| @@ -4649,37 +4671,6 @@ sfnt_read_ttc_header (int fd) | |||
| 4649 | through one of three ``zone pointer'' registers, and are accessible | 4671 | through one of three ``zone pointer'' registers, and are accessible |
| 4650 | only when a program is being run on behalf of a glyph. */ | 4672 | only when a program is being run on behalf of a glyph. */ |
| 4651 | 4673 | ||
| 4652 | /* Structure definitions for tables used by the TrueType | ||
| 4653 | interpreter. */ | ||
| 4654 | |||
| 4655 | struct sfnt_cvt_table | ||
| 4656 | { | ||
| 4657 | /* Number of elements in the control value table. */ | ||
| 4658 | size_t num_elements; | ||
| 4659 | |||
| 4660 | /* Pointer to elements in the control value table. */ | ||
| 4661 | sfnt_fword *values; | ||
| 4662 | }; | ||
| 4663 | |||
| 4664 | struct sfnt_fpgm_table | ||
| 4665 | { | ||
| 4666 | /* Number of instructions in the font program table. */ | ||
| 4667 | size_t num_instructions; | ||
| 4668 | |||
| 4669 | /* Pointer to elements in the font program table. */ | ||
| 4670 | unsigned char *instructions; | ||
| 4671 | }; | ||
| 4672 | |||
| 4673 | struct sfnt_prep_table | ||
| 4674 | { | ||
| 4675 | /* Number of instructions in the control value program (pre-program) | ||
| 4676 | table. */ | ||
| 4677 | size_t num_instructions; | ||
| 4678 | |||
| 4679 | /* Pointer to elements in the preprogram table. */ | ||
| 4680 | unsigned char *instructions; | ||
| 4681 | }; | ||
| 4682 | |||
| 4683 | 4674 | ||
| 4684 | 4675 | ||
| 4685 | /* Functions for reading tables used by the TrueType interpreter. */ | 4676 | /* Functions for reading tables used by the TrueType interpreter. */ |
| @@ -4689,7 +4680,7 @@ struct sfnt_prep_table | |||
| 4689 | in the control value table. Return NULL upon failure, else the cvt | 4680 | in the control value table. Return NULL upon failure, else the cvt |
| 4690 | table. */ | 4681 | table. */ |
| 4691 | 4682 | ||
| 4692 | static struct sfnt_cvt_table * | 4683 | TEST_STATIC struct sfnt_cvt_table * |
| 4693 | sfnt_read_cvt_table (int fd, struct sfnt_offset_subtable *subtable) | 4684 | sfnt_read_cvt_table (int fd, struct sfnt_offset_subtable *subtable) |
| 4694 | { | 4685 | { |
| 4695 | struct sfnt_table_directory *directory; | 4686 | struct sfnt_table_directory *directory; |
| @@ -4740,7 +4731,7 @@ sfnt_read_cvt_table (int fd, struct sfnt_offset_subtable *subtable) | |||
| 4740 | directory specified as SUBTABLE. Value is NULL upon failure, else | 4731 | directory specified as SUBTABLE. Value is NULL upon failure, else |
| 4741 | the fpgm table. */ | 4732 | the fpgm table. */ |
| 4742 | 4733 | ||
| 4743 | static struct sfnt_fpgm_table * | 4734 | TEST_STATIC struct sfnt_fpgm_table * |
| 4744 | sfnt_read_fpgm_table (int fd, struct sfnt_offset_subtable *subtable) | 4735 | sfnt_read_fpgm_table (int fd, struct sfnt_offset_subtable *subtable) |
| 4745 | { | 4736 | { |
| 4746 | struct sfnt_table_directory *directory; | 4737 | struct sfnt_table_directory *directory; |
| @@ -4788,7 +4779,7 @@ sfnt_read_fpgm_table (int fd, struct sfnt_offset_subtable *subtable) | |||
| 4788 | directory specified as SUBTABLE. Value is NULL upon failure, else | 4779 | directory specified as SUBTABLE. Value is NULL upon failure, else |
| 4789 | the prep table. */ | 4780 | the prep table. */ |
| 4790 | 4781 | ||
| 4791 | static struct sfnt_prep_table * | 4782 | TEST_STATIC struct sfnt_prep_table * |
| 4792 | sfnt_read_prep_table (int fd, struct sfnt_offset_subtable *subtable) | 4783 | sfnt_read_prep_table (int fd, struct sfnt_offset_subtable *subtable) |
| 4793 | { | 4784 | { |
| 4794 | struct sfnt_table_directory *directory; | 4785 | struct sfnt_table_directory *directory; |
| @@ -4836,344 +4827,6 @@ sfnt_read_prep_table (int fd, struct sfnt_offset_subtable *subtable) | |||
| 4836 | 4827 | ||
| 4837 | /* Interpreter execution environment. */ | 4828 | /* Interpreter execution environment. */ |
| 4838 | 4829 | ||
| 4839 | /* 26.6 fixed point type used within the interpreter. */ | ||
| 4840 | typedef int32_t sfnt_f26dot6; | ||
| 4841 | |||
| 4842 | /* 2.14 fixed point type used to represent versors of unit | ||
| 4843 | vectors. */ | ||
| 4844 | typedef int16_t sfnt_f2dot14; | ||
| 4845 | |||
| 4846 | /* 18.14 fixed point type used to calculate rounding details. */ | ||
| 4847 | typedef int32_t sfnt_f18dot14; | ||
| 4848 | |||
| 4849 | struct sfnt_unit_vector | ||
| 4850 | { | ||
| 4851 | /* X and Y versors of the 2d unit vector. */ | ||
| 4852 | sfnt_f2dot14 x, y; | ||
| 4853 | }; | ||
| 4854 | |||
| 4855 | struct sfnt_interpreter_definition | ||
| 4856 | { | ||
| 4857 | /* The opcode of this instruction or function. */ | ||
| 4858 | uint16_t opcode; | ||
| 4859 | |||
| 4860 | /* The number of instructions. */ | ||
| 4861 | uint16_t instruction_count; | ||
| 4862 | |||
| 4863 | /* Pointer to instructions belonging to the definition. This | ||
| 4864 | pointer points directly into the control value or font program. | ||
| 4865 | Make sure both programs are kept around as long as the | ||
| 4866 | interpreter continues to exist. */ | ||
| 4867 | unsigned char *instructions; | ||
| 4868 | }; | ||
| 4869 | |||
| 4870 | /* This structure represents a ``struct sfnt_glyph'' that has been | ||
| 4871 | scaled to a given pixel size. | ||
| 4872 | |||
| 4873 | It can either contain a simple glyph, or a decomposed compound | ||
| 4874 | glyph; instructions are interpreted for both simple glyphs, simple | ||
| 4875 | glyph components inside a compound glyph, and compound glyphs as a | ||
| 4876 | whole. | ||
| 4877 | |||
| 4878 | In addition to the glyph data itself, it also records various | ||
| 4879 | information for the instruction interpretation process: | ||
| 4880 | |||
| 4881 | - ``current'' point coordinates, which have been modified | ||
| 4882 | by the instructing process. | ||
| 4883 | |||
| 4884 | - two phantom points at the origin and the advance of the | ||
| 4885 | glyph. */ | ||
| 4886 | |||
| 4887 | struct sfnt_interpreter_zone | ||
| 4888 | { | ||
| 4889 | /* The number of points in this zone, including the two phantom | ||
| 4890 | points at the end. */ | ||
| 4891 | size_t num_points; | ||
| 4892 | |||
| 4893 | /* The number of contours in this zone. */ | ||
| 4894 | size_t num_contours; | ||
| 4895 | |||
| 4896 | /* The end points of each contour. */ | ||
| 4897 | size_t *contour_end_points; | ||
| 4898 | |||
| 4899 | /* Pointer to the X axis point data. */ | ||
| 4900 | sfnt_f26dot6 *restrict x_points; | ||
| 4901 | |||
| 4902 | /* Pointer to the X axis current point data. */ | ||
| 4903 | sfnt_f26dot6 *restrict x_current; | ||
| 4904 | |||
| 4905 | /* Pointer to the Y axis point data. */ | ||
| 4906 | sfnt_f26dot6 *restrict y_points; | ||
| 4907 | |||
| 4908 | /* Pointer to the Y axis current point data. */ | ||
| 4909 | sfnt_f26dot6 *restrict y_current; | ||
| 4910 | |||
| 4911 | /* Pointer to the flags associated with this data. */ | ||
| 4912 | unsigned char *flags; | ||
| 4913 | }; | ||
| 4914 | |||
| 4915 | enum | ||
| 4916 | { | ||
| 4917 | /* Bits 7 and 6 of a glyph point's flags is reserved. This scaler | ||
| 4918 | uses it to mean that the point has been touched in one axis or | ||
| 4919 | another. */ | ||
| 4920 | SFNT_POINT_TOUCHED_X = (1 << 7), | ||
| 4921 | SFNT_POINT_TOUCHED_Y = (1 << 6), | ||
| 4922 | SFNT_POINT_TOUCHED_BOTH = (SFNT_POINT_TOUCHED_X | ||
| 4923 | | SFNT_POINT_TOUCHED_Y), | ||
| 4924 | }; | ||
| 4925 | |||
| 4926 | /* This is needed because `round' below needs an interpreter | ||
| 4927 | argument. */ | ||
| 4928 | struct sfnt_interpreter; | ||
| 4929 | |||
| 4930 | struct sfnt_graphics_state | ||
| 4931 | { | ||
| 4932 | /* Pointer to the function used for rounding. This function is | ||
| 4933 | asymmetric, so -0.5 rounds up to 0, not -1. It is up to the | ||
| 4934 | caller to handle negative values. | ||
| 4935 | |||
| 4936 | Value is undefined unless sfnt_validate_gs has been called, and | ||
| 4937 | the second argument may be used to provide detailed rounding | ||
| 4938 | information (``super rounding state''.) */ | ||
| 4939 | sfnt_f26dot6 (*round) (sfnt_f26dot6, struct sfnt_interpreter *); | ||
| 4940 | |||
| 4941 | /* Pointer to the function used to project euclidean vectors onto | ||
| 4942 | the projection vector. Value is the magnitude of the projected | ||
| 4943 | vector. */ | ||
| 4944 | sfnt_f26dot6 (*project) (sfnt_f26dot6, sfnt_f26dot6, | ||
| 4945 | struct sfnt_interpreter *); | ||
| 4946 | |||
| 4947 | /* Pointer to the function used to project euclidean vectors onto | ||
| 4948 | the dual projection vector. Value is the magnitude of the | ||
| 4949 | projected vector. */ | ||
| 4950 | sfnt_f26dot6 (*dual_project) (sfnt_f26dot6, sfnt_f26dot6, | ||
| 4951 | struct sfnt_interpreter *); | ||
| 4952 | |||
| 4953 | /* Pointer to the function used to move specified points | ||
| 4954 | along the freedom vector by a distance specified in terms | ||
| 4955 | of the projection vector. */ | ||
| 4956 | void (*move) (sfnt_f26dot6 *restrict, | ||
| 4957 | sfnt_f26dot6 *restrict, size_t, | ||
| 4958 | struct sfnt_interpreter *, | ||
| 4959 | sfnt_f26dot6, unsigned char *); | ||
| 4960 | |||
| 4961 | /* Dot product between the freedom and the projection vectors. */ | ||
| 4962 | sfnt_f2dot14 vector_dot_product; | ||
| 4963 | |||
| 4964 | /* Controls whether the sign of control value table entries will be | ||
| 4965 | changed to match the sign of the actual distance measurement with | ||
| 4966 | which it is compared. Setting auto flip to TRUE makes it | ||
| 4967 | possible to control distances measured with or against the | ||
| 4968 | projection vector with a single control value table entry. When | ||
| 4969 | auto flip is set to FALSE, distances must be measured with the | ||
| 4970 | projection vector. */ | ||
| 4971 | bool auto_flip; | ||
| 4972 | |||
| 4973 | /* Limits the regularizing effects of control value table entries to | ||
| 4974 | cases where the difference between the table value and the | ||
| 4975 | measurement taken from the original outline is sufficiently | ||
| 4976 | small. */ | ||
| 4977 | sfnt_f26dot6 cvt_cut_in; | ||
| 4978 | |||
| 4979 | /* Establishes the base value used to calculate the range of point | ||
| 4980 | sizes to which a given DELTAC[] or DELTAP[] instruction will | ||
| 4981 | apply. The formulas given below are used to calculate the range | ||
| 4982 | of the various DELTA instructions. | ||
| 4983 | |||
| 4984 | DELTAC1 DELTAP1 (delta_base) through (delta_base + 15) | ||
| 4985 | DELTAC2 DELTAP2 (delta_base + 16) through (delta_base + 31) | ||
| 4986 | DELTAC3 DELTAP3 (delta_base + 32) through (delta_base + 47) | ||
| 4987 | |||
| 4988 | Please keep this documentation in sync with the TrueType | ||
| 4989 | reference manual. */ | ||
| 4990 | unsigned short delta_base; | ||
| 4991 | |||
| 4992 | /* Determines the range of movement and smallest magnitude of | ||
| 4993 | movement (the step) in a DELTAC[] or DELTAP[] instruction. | ||
| 4994 | Changing the value of the delta shift makes it possible to trade | ||
| 4995 | off fine control of point movement for range of movement. A low | ||
| 4996 | delta shift favors range of movement over fine control. A high | ||
| 4997 | delta shift favors fine control over range of movement. The step | ||
| 4998 | has the value 1/2 to the power delta shift. The range of | ||
| 4999 | movement is calculated by taking the number of steps allowed (16) | ||
| 5000 | and multiplying it by the step. | ||
| 5001 | |||
| 5002 | The legal range for delta shift is zero through six. Negative | ||
| 5003 | values are illegal. */ | ||
| 5004 | unsigned short delta_shift; | ||
| 5005 | |||
| 5006 | /* A second projection vector set to a line defined by the original | ||
| 5007 | outline location of two points. The dual projection vector is | ||
| 5008 | used when it is necessary to measure distances from the scaled | ||
| 5009 | outline before any instructions were executed. */ | ||
| 5010 | struct sfnt_unit_vector dual_projection_vector; | ||
| 5011 | |||
| 5012 | /* A unit vector that establishes an axis along which points can | ||
| 5013 | move. */ | ||
| 5014 | struct sfnt_unit_vector freedom_vector; | ||
| 5015 | |||
| 5016 | /* Makes it possible to turn off instructions under some | ||
| 5017 | circumstances. When flag 1 is set, changes to the graphics state | ||
| 5018 | made in the control value program will be ignored. When flag is | ||
| 5019 | 1, grid fitting instructions will be ignored. */ | ||
| 5020 | unsigned char instruct_control; | ||
| 5021 | |||
| 5022 | /* Makes it possible to repeat certain instructions a designated | ||
| 5023 | number of times. The default value of one assures that unless | ||
| 5024 | the value of loop is altered, these instructions will execute one | ||
| 5025 | time. */ | ||
| 5026 | unsigned short loop; | ||
| 5027 | |||
| 5028 | /* Establishes the smallest possible value to which a distance will | ||
| 5029 | be rounded. */ | ||
| 5030 | sfnt_f26dot6 minimum_distance; | ||
| 5031 | |||
| 5032 | /* A unit vector whose direction establishes an axis along which | ||
| 5033 | distances are measured. */ | ||
| 5034 | struct sfnt_unit_vector projection_vector; | ||
| 5035 | |||
| 5036 | /* Determines the manner in which values are rounded. Can be set to | ||
| 5037 | a number of predefined states or to a customized state with the | ||
| 5038 | SROUND or S45ROUND instructions. */ | ||
| 5039 | int round_state; | ||
| 5040 | |||
| 5041 | /* Reference points. These reference point numbers, which together | ||
| 5042 | with a zone designation, specify a point in either the glyph zone | ||
| 5043 | or the twilight zone. */ | ||
| 5044 | uint16_t rp0, rp1, rp2; | ||
| 5045 | |||
| 5046 | /* Flags which determine whether the interpreter will activate | ||
| 5047 | dropout control for the current glyph. */ | ||
| 5048 | int scan_control; | ||
| 5049 | |||
| 5050 | /* The distance difference below which the interpreter will replace | ||
| 5051 | a CVT distance or an actual distance in favor of the single width | ||
| 5052 | value. */ | ||
| 5053 | sfnt_f26dot6 sw_cut_in; | ||
| 5054 | |||
| 5055 | /* The value used in place of the control value table distance or | ||
| 5056 | the actual distance value when the difference between that | ||
| 5057 | distance and the single width value is less than the single width | ||
| 5058 | cut-in. */ | ||
| 5059 | sfnt_f26dot6 single_width_value; | ||
| 5060 | |||
| 5061 | /* Zone pointers, which reference a zone. */ | ||
| 5062 | int zp0, zp1, zp2; | ||
| 5063 | }; | ||
| 5064 | |||
| 5065 | struct sfnt_interpreter | ||
| 5066 | { | ||
| 5067 | /* The number of elements in the stack. */ | ||
| 5068 | uint16_t max_stack_elements; | ||
| 5069 | |||
| 5070 | /* The number of instructions in INSTRUCTIONS. */ | ||
| 5071 | uint16_t num_instructions; | ||
| 5072 | |||
| 5073 | /* Size of the storage area. */ | ||
| 5074 | uint16_t storage_size; | ||
| 5075 | |||
| 5076 | /* Size of the function definition area. */ | ||
| 5077 | uint16_t function_defs_size; | ||
| 5078 | |||
| 5079 | /* Size of the instruction definition area. */ | ||
| 5080 | uint16_t instruction_defs_size; | ||
| 5081 | |||
| 5082 | /* Size of the twilight zone. */ | ||
| 5083 | uint16_t twilight_zone_size; | ||
| 5084 | |||
| 5085 | /* The instruction pointer. This points to the instruction | ||
| 5086 | currently being executed. */ | ||
| 5087 | int IP; | ||
| 5088 | |||
| 5089 | /* The current scale. */ | ||
| 5090 | sfnt_fixed scale; | ||
| 5091 | |||
| 5092 | /* The current ppem and point size. */ | ||
| 5093 | int ppem, point_size; | ||
| 5094 | |||
| 5095 | /* The execution stack. This has at most max_stack_elements | ||
| 5096 | elements. */ | ||
| 5097 | uint32_t *stack; | ||
| 5098 | |||
| 5099 | /* Pointer past the top of the stack. */ | ||
| 5100 | uint32_t *SP; | ||
| 5101 | |||
| 5102 | /* The size of the control value table. */ | ||
| 5103 | size_t cvt_size; | ||
| 5104 | |||
| 5105 | /* Pointer to instructions currently being executed. */ | ||
| 5106 | unsigned char *restrict instructions; | ||
| 5107 | |||
| 5108 | /* The twilight zone. May not be NULL. */ | ||
| 5109 | sfnt_f26dot6 *restrict twilight_x, *restrict twilight_y; | ||
| 5110 | |||
| 5111 | /* The original X positions of points in the twilight zone. */ | ||
| 5112 | sfnt_f26dot6 *restrict twilight_original_x; | ||
| 5113 | |||
| 5114 | /* The original Y positions of points in the twilight zone. | ||
| 5115 | |||
| 5116 | Apple does not directly say whether or not points in the twilight | ||
| 5117 | zone can have their original positions changed. But this is | ||
| 5118 | implied by ``create points in the twilight zone''. */ | ||
| 5119 | sfnt_f26dot6 *restrict twilight_original_y; | ||
| 5120 | |||
| 5121 | /* The scaled outlines being manipulated. May be NULL. */ | ||
| 5122 | struct sfnt_interpreter_zone *glyph_zone; | ||
| 5123 | |||
| 5124 | /* The glyph advance width. Value is undefined unless GLYPH_ZONE is | ||
| 5125 | set. */ | ||
| 5126 | sfnt_f26dot6 advance_width; | ||
| 5127 | |||
| 5128 | /* The storage area. */ | ||
| 5129 | uint32_t *storage; | ||
| 5130 | |||
| 5131 | /* Control value table values. */ | ||
| 5132 | sfnt_f26dot6 *cvt; | ||
| 5133 | |||
| 5134 | /* Function definitions. */ | ||
| 5135 | struct sfnt_interpreter_definition *function_defs; | ||
| 5136 | |||
| 5137 | /* Instruction definitions. */ | ||
| 5138 | struct sfnt_interpreter_definition *instruction_defs; | ||
| 5139 | |||
| 5140 | /* Interpreter registers. */ | ||
| 5141 | struct sfnt_graphics_state state; | ||
| 5142 | |||
| 5143 | /* Detailed rounding state used when state.round_state indicates | ||
| 5144 | that fine grained rounding should be used. | ||
| 5145 | |||
| 5146 | PERIOD says how often a round value occurs, for numbers | ||
| 5147 | increasing from PHASE to infinity. | ||
| 5148 | |||
| 5149 | THRESHOLD says when to round a value between two increasing | ||
| 5150 | periods towards the larger period. */ | ||
| 5151 | sfnt_f26dot6 period, phase, threshold; | ||
| 5152 | |||
| 5153 | /* The depth of any ongoing calls. */ | ||
| 5154 | int call_depth; | ||
| 5155 | |||
| 5156 | /* Jump buffer for traps. */ | ||
| 5157 | jmp_buf trap; | ||
| 5158 | |||
| 5159 | /* What was the trap. */ | ||
| 5160 | const char *trap_reason; | ||
| 5161 | |||
| 5162 | #ifdef TEST | ||
| 5163 | /* If non-NULL, function called before each instruction is | ||
| 5164 | executed. */ | ||
| 5165 | void (*run_hook) (struct sfnt_interpreter *); | ||
| 5166 | |||
| 5167 | /* If non-NULL, function called before each stack element is | ||
| 5168 | pushed. */ | ||
| 5169 | void (*push_hook) (struct sfnt_interpreter *, uint32_t); | ||
| 5170 | |||
| 5171 | /* If non-NULL, function called before each stack element is | ||
| 5172 | popped. */ | ||
| 5173 | void (*pop_hook) (struct sfnt_interpreter *, uint32_t); | ||
| 5174 | #endif | ||
| 5175 | }; | ||
| 5176 | |||
| 5177 | /* Divide the specified two 26.6 fixed point numbers X and Y. | 4830 | /* Divide the specified two 26.6 fixed point numbers X and Y. |
| 5178 | Return the result. */ | 4831 | Return the result. */ |
| 5179 | 4832 | ||
| @@ -5409,7 +5062,7 @@ sfnt_init_graphics_state (struct sfnt_graphics_state *state) | |||
| 5409 | Value is the interpreter, with all state initialized to default | 5062 | Value is the interpreter, with all state initialized to default |
| 5410 | values, or NULL upon failure. */ | 5063 | values, or NULL upon failure. */ |
| 5411 | 5064 | ||
| 5412 | static struct sfnt_interpreter * | 5065 | TEST_STATIC struct sfnt_interpreter * |
| 5413 | sfnt_make_interpreter (struct sfnt_maxp_table *maxp, | 5066 | sfnt_make_interpreter (struct sfnt_maxp_table *maxp, |
| 5414 | struct sfnt_cvt_table *cvt, | 5067 | struct sfnt_cvt_table *cvt, |
| 5415 | struct sfnt_head_table *head, | 5068 | struct sfnt_head_table *head, |
| @@ -5661,13 +5314,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 5661 | _value); \ | 5314 | _value); \ |
| 5662 | _value;})) | 5315 | _value;})) |
| 5663 | 5316 | ||
| 5664 | #define POP_UNCHECKED() \ | 5317 | #define POP_UNCHECKED() POP () |
| 5665 | ({uint32_t _value; \ | ||
| 5666 | _value = *(--interpreter->SP); \ | ||
| 5667 | if (interpreter->pop_hook) \ | ||
| 5668 | interpreter->pop_hook (interpreter, \ | ||
| 5669 | _value); \ | ||
| 5670 | _value;}) | ||
| 5671 | 5318 | ||
| 5672 | #endif | 5319 | #endif |
| 5673 | 5320 | ||
| @@ -5710,15 +5357,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 5710 | interpreter->SP++; \ | 5357 | interpreter->SP++; \ |
| 5711 | } | 5358 | } |
| 5712 | 5359 | ||
| 5713 | #define PUSH_UNCHECKED(value) \ | 5360 | #define PUSH_UNCHECKED(value) PUSH (value) |
| 5714 | { \ | ||
| 5715 | if (interpreter->push_hook) \ | ||
| 5716 | interpreter->push_hook (interpreter, \ | ||
| 5717 | value); \ | ||
| 5718 | \ | ||
| 5719 | *interpreter->SP = value; \ | ||
| 5720 | interpreter->SP++; \ | ||
| 5721 | } | ||
| 5722 | 5361 | ||
| 5723 | #endif | 5362 | #endif |
| 5724 | 5363 | ||
| @@ -6722,8 +6361,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6722 | if (!n) \ | 6361 | if (!n) \ |
| 6723 | break; \ | 6362 | break; \ |
| 6724 | \ | 6363 | \ |
| 6725 | argn = POP (); \ | ||
| 6726 | pn = POP (); \ | 6364 | pn = POP (); \ |
| 6365 | argn = POP (); \ | ||
| 6727 | sfnt_deltap (1, interpreter, argn, pn); \ | 6366 | sfnt_deltap (1, interpreter, argn, pn); \ |
| 6728 | n--; \ | 6367 | n--; \ |
| 6729 | goto deltap1_start; \ | 6368 | goto deltap1_start; \ |
| @@ -6739,8 +6378,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6739 | if (!n) \ | 6378 | if (!n) \ |
| 6740 | break; \ | 6379 | break; \ |
| 6741 | \ | 6380 | \ |
| 6742 | argn = POP (); \ | ||
| 6743 | pn = POP (); \ | 6381 | pn = POP (); \ |
| 6382 | argn = POP (); \ | ||
| 6744 | sfnt_deltap (2, interpreter, argn, pn); \ | 6383 | sfnt_deltap (2, interpreter, argn, pn); \ |
| 6745 | n--; \ | 6384 | n--; \ |
| 6746 | goto deltap2_start; \ | 6385 | goto deltap2_start; \ |
| @@ -6756,8 +6395,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, | |||
| 6756 | if (!n) \ | 6395 | if (!n) \ |
| 6757 | break; \ | 6396 | break; \ |
| 6758 | \ | 6397 | \ |
| 6759 | argn = POP (); \ | ||
| 6760 | pn = POP (); \ | 6398 | pn = POP (); \ |
| 6399 | argn = POP (); \ | ||
| 6761 | sfnt_deltap (3, interpreter, argn, pn); \ | 6400 | sfnt_deltap (3, interpreter, argn, pn); \ |
| 6762 | n--; \ | 6401 | n--; \ |
| 6763 | goto deltap3_start; \ | 6402 | goto deltap3_start; \ |
| @@ -8394,7 +8033,7 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter) | |||
| 8394 | 8033 | ||
| 8395 | static void | 8034 | static void |
| 8396 | sfnt_deltac (int number, struct sfnt_interpreter *interpreter, | 8035 | sfnt_deltac (int number, struct sfnt_interpreter *interpreter, |
| 8397 | unsigned char operand, unsigned int index) | 8036 | unsigned int index, unsigned char operand) |
| 8398 | { | 8037 | { |
| 8399 | int ppem, delta; | 8038 | int ppem, delta; |
| 8400 | 8039 | ||
| @@ -8565,6 +8204,8 @@ sfnt_deltap (int number, struct sfnt_interpreter *interpreter, | |||
| 8565 | { | 8204 | { |
| 8566 | int ppem, delta; | 8205 | int ppem, delta; |
| 8567 | 8206 | ||
| 8207 | return; | ||
| 8208 | |||
| 8568 | /* Extract the ppem from OPERAND. The format is the same as in | 8209 | /* Extract the ppem from OPERAND. The format is the same as in |
| 8569 | sfnt_deltac. */ | 8210 | sfnt_deltac. */ |
| 8570 | 8211 | ||
| @@ -9699,26 +9340,31 @@ sfnt_interpret_shp (struct sfnt_interpreter *interpreter, | |||
| 9699 | \ | 9340 | \ |
| 9700 | i = touch_start + 1; \ | 9341 | i = touch_start + 1; \ |
| 9701 | \ | 9342 | \ |
| 9702 | for (; i <= end; ++i) \ | 9343 | while (i != touch_end) \ |
| 9703 | { \ | 9344 | { \ |
| 9704 | if (i > end) \ | ||
| 9705 | i = start; \ | ||
| 9706 | \ | ||
| 9707 | /* Movement is always relative to the original position of \ | 9345 | /* Movement is always relative to the original position of \ |
| 9708 | the point. */ \ | 9346 | the point. */ \ |
| 9709 | position = load_original (i); \ | 9347 | position = load_original (i); \ |
| 9710 | \ | 9348 | \ |
| 9711 | /* If i is in between touch_start and touch_end... */ \ | 9349 | /* If i is in between touch_start and touch_end... */ \ |
| 9712 | if (position >= original_min_pos \ | 9350 | if (position >= original_min_pos \ |
| 9713 | && position <= original_max_pos \ | 9351 | && position <= original_max_pos) \ |
| 9714 | && original_min_pos != original_max_pos) \ | ||
| 9715 | { \ | 9352 | { \ |
| 9716 | /* ... preserve the ratio of i between min_pos and \ | 9353 | /* Handle the degenerate case where original_min_pos and \ |
| 9717 | max_pos... */ \ | 9354 | original_max_pos have not changed by placing the point in \ |
| 9718 | ratio = sfnt_div_fixed (sfnt_sub (position, \ | 9355 | the middle. */ \ |
| 9719 | original_min_pos) * 1024, \ | 9356 | if (original_min_pos == original_max_pos) \ |
| 9720 | sfnt_sub (original_max_pos, \ | 9357 | ratio = 077777; \ |
| 9721 | original_min_pos) * 1024); \ | 9358 | else \ |
| 9359 | /* ... preserve the ratio of i between min_pos and \ | ||
| 9360 | max_pos... */ \ | ||
| 9361 | ratio = sfnt_div_fixed ((sfnt_sub (position, \ | ||
| 9362 | original_min_pos) \ | ||
| 9363 | * 1024), \ | ||
| 9364 | (sfnt_sub (original_max_pos, \ | ||
| 9365 | original_min_pos) \ | ||
| 9366 | * 1024)); \ | ||
| 9367 | \ | ||
| 9722 | delta = sfnt_sub (max_pos, min_pos); \ | 9368 | delta = sfnt_sub (max_pos, min_pos); \ |
| 9723 | delta = sfnt_mul_fixed (ratio, delta); \ | 9369 | delta = sfnt_mul_fixed (ratio, delta); \ |
| 9724 | store_point (i, sfnt_add (min_pos, delta)); \ | 9370 | store_point (i, sfnt_add (min_pos, delta)); \ |
| @@ -9735,6 +9381,9 @@ sfnt_interpret_shp (struct sfnt_interpreter *interpreter, | |||
| 9735 | \ | 9381 | \ |
| 9736 | store_point (i, sfnt_add (position, delta)); \ | 9382 | store_point (i, sfnt_add (position, delta)); \ |
| 9737 | } \ | 9383 | } \ |
| 9384 | \ | ||
| 9385 | if (++i > end) \ | ||
| 9386 | i = start; \ | ||
| 9738 | } \ | 9387 | } \ |
| 9739 | 9388 | ||
| 9740 | /* Interpolate untouched points in the contour between and including | 9389 | /* Interpolate untouched points in the contour between and including |
| @@ -10711,9 +10360,12 @@ sfnt_interpret_run (struct sfnt_interpreter *interpreter, | |||
| 10711 | undefined. | 10360 | undefined. |
| 10712 | 10361 | ||
| 10713 | Value is NULL upon success, else it is a string describing the | 10362 | Value is NULL upon success, else it is a string describing the |
| 10714 | reason for failure. */ | 10363 | reason for failure. |
| 10715 | 10364 | ||
| 10716 | static const char * | 10365 | The caller must save the graphics state after interpreting the font |
| 10366 | program and restore it prior to instructing each glyph. */ | ||
| 10367 | |||
| 10368 | TEST_STATIC const char * | ||
| 10717 | sfnt_interpret_font_program (struct sfnt_interpreter *interpreter, | 10369 | sfnt_interpret_font_program (struct sfnt_interpreter *interpreter, |
| 10718 | struct sfnt_fpgm_table *fpgm) | 10370 | struct sfnt_fpgm_table *fpgm) |
| 10719 | { | 10371 | { |
| @@ -10735,9 +10387,13 @@ sfnt_interpret_font_program (struct sfnt_interpreter *interpreter, | |||
| 10735 | 10387 | ||
| 10736 | Return NULL and the graphics state after the execution of the | 10388 | Return NULL and the graphics state after the execution of the |
| 10737 | program in *STATE, or a string describing the reason for a failure | 10389 | program in *STATE, or a string describing the reason for a failure |
| 10738 | to interpret the program. */ | 10390 | to interpret the program. |
| 10739 | 10391 | ||
| 10740 | static const char * | 10392 | The caller must save the graphics state after interpreting the |
| 10393 | control value program and restore it prior to instructing each | ||
| 10394 | glyph. */ | ||
| 10395 | |||
| 10396 | TEST_STATIC const char * | ||
| 10741 | sfnt_interpret_control_value_program (struct sfnt_interpreter *interpreter, | 10397 | sfnt_interpret_control_value_program (struct sfnt_interpreter *interpreter, |
| 10742 | struct sfnt_prep_table *prep, | 10398 | struct sfnt_prep_table *prep, |
| 10743 | struct sfnt_graphics_state *state) | 10399 | struct sfnt_graphics_state *state) |
| @@ -10776,30 +10432,6 @@ sfnt_interpret_control_value_program (struct sfnt_interpreter *interpreter, | |||
| 10776 | scaling separately. It might be nice to fix that in the | 10432 | scaling separately. It might be nice to fix that in the |
| 10777 | future. */ | 10433 | future. */ |
| 10778 | 10434 | ||
| 10779 | /* Structure describing a single scaled and fitted outline. */ | ||
| 10780 | |||
| 10781 | struct sfnt_instructed_outline | ||
| 10782 | { | ||
| 10783 | /* The number of points in this contour, including the two phantom | ||
| 10784 | points at the end. */ | ||
| 10785 | size_t num_points; | ||
| 10786 | |||
| 10787 | /* The number of contours in this outline. */ | ||
| 10788 | size_t num_contours; | ||
| 10789 | |||
| 10790 | /* The end points of each contour. */ | ||
| 10791 | size_t *contour_end_points; | ||
| 10792 | |||
| 10793 | /* The points of each contour, with two additional phantom points at | ||
| 10794 | the end. */ | ||
| 10795 | sfnt_f26dot6 *restrict x_points, *restrict y_points; | ||
| 10796 | |||
| 10797 | /* The flags of each point. */ | ||
| 10798 | unsigned char *flags; | ||
| 10799 | }; | ||
| 10800 | |||
| 10801 | |||
| 10802 | |||
| 10803 | /* Instructed glyph outline decomposition. This is separate from | 10435 | /* Instructed glyph outline decomposition. This is separate from |
| 10804 | sfnt_decompose_glyph because this file should be able to be built | 10436 | sfnt_decompose_glyph because this file should be able to be built |
| 10805 | with instructions disabled. */ | 10437 | with instructions disabled. */ |
| @@ -10958,12 +10590,14 @@ sfnt_decompose_instructed_outline (struct sfnt_instructed_outline *outline, | |||
| 10958 | 10590 | ||
| 10959 | This function is not reentrant. */ | 10591 | This function is not reentrant. */ |
| 10960 | 10592 | ||
| 10961 | static struct sfnt_glyph_outline * | 10593 | TEST_STATIC struct sfnt_glyph_outline * |
| 10962 | sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed) | 10594 | sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed) |
| 10963 | { | 10595 | { |
| 10964 | struct sfnt_glyph_outline *outline; | 10596 | struct sfnt_glyph_outline *outline; |
| 10965 | int rc; | 10597 | int rc; |
| 10966 | 10598 | ||
| 10599 | memset (&build_outline_context, 0, sizeof build_outline_context); | ||
| 10600 | |||
| 10967 | /* Allocate the outline now with enough for 44 words at the end. */ | 10601 | /* Allocate the outline now with enough for 44 words at the end. */ |
| 10968 | outline = xmalloc (sizeof *outline + 40 * sizeof (*outline->outline)); | 10602 | outline = xmalloc (sizeof *outline + 40 * sizeof (*outline->outline)); |
| 10969 | outline->outline_size = 40; | 10603 | outline->outline_size = 40; |
| @@ -11047,7 +10681,7 @@ sfnt_compute_phantom_points (struct sfnt_glyph *glyph, | |||
| 11047 | Upon success, return NULL and the resulting points and contours in | 10681 | Upon success, return NULL and the resulting points and contours in |
| 11048 | *VALUE. Else, value is the reason interpretation failed. */ | 10682 | *VALUE. Else, value is the reason interpretation failed. */ |
| 11049 | 10683 | ||
| 11050 | static const char * | 10684 | TEST_STATIC const char * |
| 11051 | sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph, | 10685 | sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph, |
| 11052 | struct sfnt_interpreter *interpreter, | 10686 | struct sfnt_interpreter *interpreter, |
| 11053 | struct sfnt_glyph_metrics *metrics, | 10687 | struct sfnt_glyph_metrics *metrics, |
| @@ -11445,12 +11079,16 @@ sfnt_test_edge (struct sfnt_edge *edges, size_t num_edges, | |||
| 11445 | } | 11079 | } |
| 11446 | 11080 | ||
| 11447 | static void | 11081 | static void |
| 11448 | sfnt_x_raster (struct sfnt_raster *raster) | 11082 | sfnt_x_raster (struct sfnt_raster **rasters, |
| 11083 | int *advances, | ||
| 11084 | int nrasters, | ||
| 11085 | struct sfnt_hhea_table *hhea, | ||
| 11086 | sfnt_fixed scale) | ||
| 11449 | { | 11087 | { |
| 11450 | Display *display; | 11088 | Display *display; |
| 11451 | Window window; | 11089 | Window window; |
| 11452 | Pixmap pixmap; | 11090 | Pixmap *pixmaps; |
| 11453 | Picture glyph, drawable, solid; | 11091 | Picture *glyphs, drawable, solid; |
| 11454 | int event_base, error_base; | 11092 | int event_base, error_base; |
| 11455 | int major, minor, *depths, count; | 11093 | int major, minor, *depths, count; |
| 11456 | XRenderPictFormat *format, *glyph_format; | 11094 | XRenderPictFormat *format, *glyph_format; |
| @@ -11460,7 +11098,11 @@ sfnt_x_raster (struct sfnt_raster *raster) | |||
| 11460 | XGCValues gcvalues; | 11098 | XGCValues gcvalues; |
| 11461 | XEvent event; | 11099 | XEvent event; |
| 11462 | XRenderColor white, black; | 11100 | XRenderColor white, black; |
| 11463 | int i; | 11101 | int i, ascent, origin, x, y; |
| 11102 | Font font; | ||
| 11103 | |||
| 11104 | if (!nrasters) | ||
| 11105 | exit (0); | ||
| 11464 | 11106 | ||
| 11465 | display = XOpenDisplay (NULL); | 11107 | display = XOpenDisplay (NULL); |
| 11466 | 11108 | ||
| @@ -11475,7 +11117,7 @@ sfnt_x_raster (struct sfnt_raster *raster) | |||
| 11475 | exit (0); | 11117 | exit (0); |
| 11476 | 11118 | ||
| 11477 | window = XCreateSimpleWindow (display, DefaultRootWindow (display), | 11119 | window = XCreateSimpleWindow (display, DefaultRootWindow (display), |
| 11478 | 0, 0, 40, 40, 0, 0, | 11120 | 0, 0, 100, 150, 0, 0, |
| 11479 | WhitePixel (display, | 11121 | WhitePixel (display, |
| 11480 | DefaultScreen (display))); | 11122 | DefaultScreen (display))); |
| 11481 | XSelectInput (display, window, ExposureMask); | 11123 | XSelectInput (display, window, ExposureMask); |
| @@ -11501,37 +11143,57 @@ sfnt_x_raster (struct sfnt_raster *raster) | |||
| 11501 | depth_found: | 11143 | depth_found: |
| 11502 | 11144 | ||
| 11503 | XFree (depths); | 11145 | XFree (depths); |
| 11504 | pixmap = XCreatePixmap (display, DefaultRootWindow (display), | 11146 | pixmaps = alloca (sizeof *pixmaps * nrasters); |
| 11505 | raster->width, raster->height, 8); | 11147 | glyphs = alloca (sizeof *glyphs * nrasters); |
| 11506 | 11148 | gc = None; | |
| 11507 | /* Upload the raster. */ | 11149 | |
| 11508 | image.width = raster->width; | 11150 | for (i = 0; i < nrasters; ++i) |
| 11509 | image.height = raster->height; | 11151 | { |
| 11510 | image.xoffset = 0; | 11152 | pixmaps[i] = XCreatePixmap (display, DefaultRootWindow (display), |
| 11511 | image.format = ZPixmap; | 11153 | rasters[i]->width, rasters[i]->height, 8); |
| 11512 | image.data = (char *) raster->cells; | 11154 | if (!gc) |
| 11513 | image.byte_order = MSBFirst; | 11155 | gc = XCreateGC (display, pixmaps[i], 0, &gcvalues); |
| 11514 | image.bitmap_unit = 8; | 11156 | |
| 11515 | image.bitmap_bit_order = LSBFirst; | 11157 | /* Upload the raster. */ |
| 11516 | image.bitmap_pad = SFNT_POLY_ALIGNMENT * 8; | 11158 | image.width = rasters[i]->width; |
| 11517 | image.depth = 8; | 11159 | image.height = rasters[i]->height; |
| 11518 | image.bytes_per_line = raster->stride; | 11160 | image.xoffset = 0; |
| 11519 | image.bits_per_pixel = 8; | 11161 | image.format = ZPixmap; |
| 11520 | image.red_mask = 0; | 11162 | image.data = (char *) rasters[i]->cells; |
| 11521 | image.green_mask = 0; | 11163 | image.byte_order = MSBFirst; |
| 11522 | image.blue_mask = 0; | 11164 | image.bitmap_unit = 8; |
| 11523 | 11165 | image.bitmap_bit_order = LSBFirst; | |
| 11524 | if (!XInitImage (&image)) | 11166 | image.bitmap_pad = SFNT_POLY_ALIGNMENT * 8; |
| 11525 | abort (); | 11167 | image.depth = 8; |
| 11168 | image.bytes_per_line = rasters[i]->stride; | ||
| 11169 | image.bits_per_pixel = 8; | ||
| 11170 | image.red_mask = 0; | ||
| 11171 | image.green_mask = 0; | ||
| 11172 | image.blue_mask = 0; | ||
| 11173 | |||
| 11174 | if (!XInitImage (&image)) | ||
| 11175 | abort (); | ||
| 11176 | |||
| 11177 | XPutImage (display, pixmaps[i], gc, &image, | ||
| 11178 | 0, 0, 0, 0, image.width, image.height); | ||
| 11179 | |||
| 11180 | glyphs[i] = XRenderCreatePicture (display, pixmaps[i], | ||
| 11181 | glyph_format, 0, NULL); | ||
| 11182 | } | ||
| 11526 | 11183 | ||
| 11527 | gc = XCreateGC (display, pixmap, 0, &gcvalues); | 11184 | XFreeGC (display, gc); |
| 11528 | XPutImage (display, pixmap, gc, &image, | 11185 | |
| 11529 | 0, 0, 0, 0, image.width, image.height); | 11186 | font = XLoadFont (display, "6x13"); |
| 11187 | |||
| 11188 | if (!font) | ||
| 11189 | exit (1); | ||
| 11190 | |||
| 11191 | gcvalues.font = font; | ||
| 11192 | gcvalues.foreground = BlackPixel (display, DefaultScreen (display)); | ||
| 11193 | gc = XCreateGC (display, window, GCForeground | GCFont, &gcvalues); | ||
| 11530 | 11194 | ||
| 11531 | drawable = XRenderCreatePicture (display, window, format, | 11195 | drawable = XRenderCreatePicture (display, window, format, |
| 11532 | 0, NULL); | 11196 | 0, NULL); |
| 11533 | glyph = XRenderCreatePicture (display, pixmap, glyph_format, | ||
| 11534 | 0, NULL); | ||
| 11535 | memset (&black, 0, sizeof black); | 11197 | memset (&black, 0, sizeof black); |
| 11536 | black.alpha = 65535; | 11198 | black.alpha = 65535; |
| 11537 | 11199 | ||
| @@ -11552,18 +11214,35 @@ sfnt_x_raster (struct sfnt_raster *raster) | |||
| 11552 | XRenderFillRectangle (display, PictOpSrc, drawable, | 11214 | XRenderFillRectangle (display, PictOpSrc, drawable, |
| 11553 | &white, 0, 0, 65535, 65535); | 11215 | &white, 0, 0, 65535, 65535); |
| 11554 | 11216 | ||
| 11555 | /* Draw the solid fill with the glyph as clip mask. */ | 11217 | /* Compute ascent line. */ |
| 11556 | XRenderComposite (display, PictOpOver, solid, glyph, | 11218 | ascent = sfnt_mul_fixed (hhea->ascent * 65536, |
| 11557 | drawable, 0, 0, 0, 0, 0, 0, | 11219 | scale) / 65536; |
| 11558 | raster->width, raster->height); | 11220 | |
| 11221 | origin = 0; | ||
| 11222 | |||
| 11223 | for (i = 0; i < nrasters; ++i) | ||
| 11224 | { | ||
| 11225 | /* Compute the base position. */ | ||
| 11226 | x = origin + rasters[i]->offx; | ||
| 11227 | y = ascent - rasters[i]->height - rasters[i]->offy; | ||
| 11228 | |||
| 11229 | /* Draw the solid fill with the glyph as clip mask. */ | ||
| 11230 | XRenderComposite (display, PictOpOver, solid, glyphs[i], | ||
| 11231 | drawable, 0, 0, 0, 0, x, y, | ||
| 11232 | rasters[i]->width, rasters[i]->height); | ||
| 11233 | |||
| 11234 | origin += advances[i]; | ||
| 11235 | } | ||
| 11559 | } | 11236 | } |
| 11560 | } | 11237 | } |
| 11561 | } | 11238 | } |
| 11562 | 11239 | ||
| 11563 | static void | 11240 | static void |
| 11564 | sfnt_test_raster (struct sfnt_raster *raster) | 11241 | sfnt_test_raster (struct sfnt_raster *raster, |
| 11242 | struct sfnt_hhea_table *hhea, | ||
| 11243 | sfnt_fixed scale) | ||
| 11565 | { | 11244 | { |
| 11566 | int x, y; | 11245 | int x, y, i; |
| 11567 | 11246 | ||
| 11568 | for (y = 0; y < raster->height; ++y) | 11247 | for (y = 0; y < raster->height; ++y) |
| 11569 | { | 11248 | { |
| @@ -11572,10 +11251,12 @@ sfnt_test_raster (struct sfnt_raster *raster) | |||
| 11572 | puts (""); | 11251 | puts (""); |
| 11573 | } | 11252 | } |
| 11574 | 11253 | ||
| 11575 | if (getenv ("SFNT_X")) | 11254 | if (hhea && getenv ("SFNT_X")) |
| 11576 | { | 11255 | { |
| 11256 | i = 0; | ||
| 11257 | |||
| 11577 | if (!fork ()) | 11258 | if (!fork ()) |
| 11578 | sfnt_x_raster (raster); | 11259 | sfnt_x_raster (&raster, &i, 1, hhea, scale); |
| 11579 | } | 11260 | } |
| 11580 | } | 11261 | } |
| 11581 | 11262 | ||
| @@ -14074,12 +13755,12 @@ static struct sfnt_interpreter_test all_tests[] = | |||
| 14074 | SDB[] ; delta base now 2 | 13755 | SDB[] ; delta base now 2 |
| 14075 | PUSHB[0] 6 | 13756 | PUSHB[0] 6 |
| 14076 | SDS[] ; delta shift now 6 | 13757 | SDS[] ; delta shift now 6 |
| 14077 | PUSHB[2] 1 0xff 1 ; CVT index 5, ppem 15 + 2, magnitude 15 | 13758 | PUSHB[2] 0xff 5 1 ; CVT index 5, ppem 15 + 2, magnitude 15 |
| 14078 | DELTAC1[] | 13759 | DELTAC1[] |
| 14079 | PUSHB[0] 1 | 13760 | PUSHB[0] 1 |
| 14080 | RCVT[] ; CVT index 5 should now be greater by 8 / 64 | 13761 | RCVT[] ; CVT index 5 should now be greater by 8 / 64 |
| 14081 | 13762 | ||
| 14082 | PUSHB[2] 1 0xef 1 ; CVT index 5, ppem 14 + 2, magnitude 15 | 13763 | PUSHB[2] 0xef 5 1 ; CVT index 5, ppem 14 + 2, magnitude 15 |
| 14083 | DELTAC1[] | 13764 | DELTAC1[] |
| 14084 | PUSHB[0] 1 | 13765 | PUSHB[0] 1 |
| 14085 | RCVT[] ; CVT index 5 should be unchanged */ | 13766 | RCVT[] ; CVT index 5 should be unchanged */ |
| @@ -14087,11 +13768,11 @@ static struct sfnt_interpreter_test all_tests[] = | |||
| 14087 | 0x5e, | 13768 | 0x5e, |
| 14088 | 0xb0, 6, | 13769 | 0xb0, 6, |
| 14089 | 0x5f, | 13770 | 0x5f, |
| 14090 | 0xb2, 5, 255, 1, | 13771 | 0xb2, 255, 5, 1, |
| 14091 | 0x73, | 13772 | 0x73, |
| 14092 | 0xb0, 5, | 13773 | 0xb0, 5, |
| 14093 | 0x45, | 13774 | 0x45, |
| 14094 | 0xb2, 5, 239, 1, | 13775 | 0xb2, 239, 5, 1, |
| 14095 | 0x73, | 13776 | 0x73, |
| 14096 | 0xb0, 5, | 13777 | 0xb0, 5, |
| 14097 | 0x45, }, | 13778 | 0x45, }, |
| @@ -14105,12 +13786,12 @@ static struct sfnt_interpreter_test all_tests[] = | |||
| 14105 | SDB[] ; delta base now 2 | 13786 | SDB[] ; delta base now 2 |
| 14106 | PUSHB[0] 6 | 13787 | PUSHB[0] 6 |
| 14107 | SDS[] ; delta shift now 6 | 13788 | SDS[] ; delta shift now 6 |
| 14108 | PUSHB[2] 1 0xff 1 ; CVT index 5, ppem 15 + 2 + 16, magnitude 15 | 13789 | PUSHB[2] 0xff 5 1 ; CVT index 5, ppem 15 + 2 + 16, magnitude 15 |
| 14109 | DELTAC2[] | 13790 | DELTAC2[] |
| 14110 | PUSHB[0] 1 | 13791 | PUSHB[0] 1 |
| 14111 | RCVT[] ; CVT index 5 should be unchanged | 13792 | RCVT[] ; CVT index 5 should be unchanged |
| 14112 | 13793 | ||
| 14113 | PUSHB[2] 1 0xef 1 ; CVT index 5, ppem 14 + 2 + 16, magnitude 15 | 13794 | PUSHB[2] 0xef 5 1 ; CVT index 5, ppem 14 + 2 + 16, magnitude 15 |
| 14114 | DELTAC2[] | 13795 | DELTAC2[] |
| 14115 | PUSHB[0] 1 | 13796 | PUSHB[0] 1 |
| 14116 | RCVT[] ; CVT index 5 should be unchanged */ | 13797 | RCVT[] ; CVT index 5 should be unchanged */ |
| @@ -14118,11 +13799,11 @@ static struct sfnt_interpreter_test all_tests[] = | |||
| 14118 | 0x5e, | 13799 | 0x5e, |
| 14119 | 0xb0, 6, | 13800 | 0xb0, 6, |
| 14120 | 0x5f, | 13801 | 0x5f, |
| 14121 | 0xb2, 5, 255, 1, | 13802 | 0xb2, 255, 5, 1, |
| 14122 | 0x74, | 13803 | 0x74, |
| 14123 | 0xb0, 5, | 13804 | 0xb0, 5, |
| 14124 | 0x45, | 13805 | 0x45, |
| 14125 | 0xb2, 5, 239, 1, | 13806 | 0xb2, 239, 5, 1, |
| 14126 | 0x74, | 13807 | 0x74, |
| 14127 | 0xb0, 5, | 13808 | 0xb0, 5, |
| 14128 | 0x45, }, | 13809 | 0x45, }, |
| @@ -14136,12 +13817,12 @@ static struct sfnt_interpreter_test all_tests[] = | |||
| 14136 | SDB[] ; delta base now 2 | 13817 | SDB[] ; delta base now 2 |
| 14137 | PUSHB[0] 6 | 13818 | PUSHB[0] 6 |
| 14138 | SDS[] ; delta shift now 6 | 13819 | SDS[] ; delta shift now 6 |
| 14139 | PUSHB[2] 1 0xff 1 ; CVT index 5, ppem 15 + 2 + 32, magnitude 15 | 13820 | PUSHB[2] 0xff 5 1 ; CVT index 5, ppem 15 + 2 + 32, magnitude 15 |
| 14140 | DELTAC3[] | 13821 | DELTAC3[] |
| 14141 | PUSHB[0] 1 | 13822 | PUSHB[0] 1 |
| 14142 | RCVT[] ; CVT index 5 should be unchanged | 13823 | RCVT[] ; CVT index 5 should be unchanged |
| 14143 | 13824 | ||
| 14144 | PUSHB[2] 1 0xef 1 ; CVT index 5, ppem 14 + 2 + 32, magnitude 15 | 13825 | PUSHB[2] 0xef 5 1 ; CVT index 5, ppem 14 + 2 + 32, magnitude 15 |
| 14145 | DELTAC3[] | 13826 | DELTAC3[] |
| 14146 | PUSHB[0] 1 | 13827 | PUSHB[0] 1 |
| 14147 | RCVT[] ; CVT index 5 should be unchanged */ | 13828 | RCVT[] ; CVT index 5 should be unchanged */ |
| @@ -14149,11 +13830,11 @@ static struct sfnt_interpreter_test all_tests[] = | |||
| 14149 | 0x5e, | 13830 | 0x5e, |
| 14150 | 0xb0, 6, | 13831 | 0xb0, 6, |
| 14151 | 0x5f, | 13832 | 0x5f, |
| 14152 | 0xb2, 5, 255, 1, | 13833 | 0xb2, 255, 5, 1, |
| 14153 | 0x75, | 13834 | 0x75, |
| 14154 | 0xb0, 5, | 13835 | 0xb0, 5, |
| 14155 | 0x45, | 13836 | 0x45, |
| 14156 | 0xb2, 5, 239, 1, | 13837 | 0xb2, 239, 5, 1, |
| 14157 | 0x75, | 13838 | 0x75, |
| 14158 | 0xb0, 5, | 13839 | 0xb0, 5, |
| 14159 | 0x45, }, | 13840 | 0x45, }, |
| @@ -14818,15 +14499,22 @@ sfnt_verbose (struct sfnt_interpreter *interpreter) | |||
| 14818 | temp.x_points = interpreter->glyph_zone->x_current; | 14499 | temp.x_points = interpreter->glyph_zone->x_current; |
| 14819 | temp.y_points = interpreter->glyph_zone->y_current; | 14500 | temp.y_points = interpreter->glyph_zone->y_current; |
| 14820 | temp.flags = interpreter->glyph_zone->flags; | 14501 | temp.flags = interpreter->glyph_zone->flags; |
| 14502 | |||
| 14821 | outline = sfnt_build_instructed_outline (&temp); | 14503 | outline = sfnt_build_instructed_outline (&temp); |
| 14822 | 14504 | ||
| 14823 | if (!outline) | 14505 | if (!outline) |
| 14824 | return; | 14506 | return; |
| 14825 | 14507 | ||
| 14508 | printf ("outline bounds: %g %g, %g %g\n", | ||
| 14509 | sfnt_coerce_fixed (outline->xmin), | ||
| 14510 | sfnt_coerce_fixed (outline->ymin), | ||
| 14511 | sfnt_coerce_fixed (outline->xmax), | ||
| 14512 | sfnt_coerce_fixed (outline->ymax)); | ||
| 14513 | |||
| 14826 | raster = sfnt_raster_glyph_outline (outline); | 14514 | raster = sfnt_raster_glyph_outline (outline); |
| 14827 | 14515 | ||
| 14828 | if (raster) | 14516 | if (raster) |
| 14829 | sfnt_test_raster (raster); | 14517 | sfnt_test_raster (raster, NULL, 0); |
| 14830 | 14518 | ||
| 14831 | xfree (outline); | 14519 | xfree (outline); |
| 14832 | xfree (raster); | 14520 | xfree (raster); |
| @@ -14937,6 +14625,11 @@ main (int argc, char **argv) | |||
| 14937 | struct sfnt_prep_table *prep; | 14625 | struct sfnt_prep_table *prep; |
| 14938 | struct sfnt_graphics_state state; | 14626 | struct sfnt_graphics_state state; |
| 14939 | struct sfnt_instructed_outline *value; | 14627 | struct sfnt_instructed_outline *value; |
| 14628 | sfnt_fixed scale; | ||
| 14629 | char *fancy; | ||
| 14630 | int *advances; | ||
| 14631 | struct sfnt_raster **rasters; | ||
| 14632 | size_t length; | ||
| 14940 | 14633 | ||
| 14941 | if (argc != 2) | 14634 | if (argc != 2) |
| 14942 | return 1; | 14635 | return 1; |
| @@ -15025,6 +14718,9 @@ main (int argc, char **argv) | |||
| 15025 | data[i]->format); | 14718 | data[i]->format); |
| 15026 | } | 14719 | } |
| 15027 | 14720 | ||
| 14721 | #define FANCY_PPEM 30 | ||
| 14722 | #define EASY_PPEM 30 | ||
| 14723 | |||
| 15028 | interpreter = NULL; | 14724 | interpreter = NULL; |
| 15029 | head = sfnt_read_head_table (fd, font); | 14725 | head = sfnt_read_head_table (fd, font); |
| 15030 | hhea = sfnt_read_hhea_table (fd, font); | 14726 | hhea = sfnt_read_hhea_table (fd, font); |
| @@ -15040,6 +14736,123 @@ main (int argc, char **argv) | |||
| 15040 | exec_prep = prep; | 14736 | exec_prep = prep; |
| 15041 | exec_fpgm = fpgm; | 14737 | exec_fpgm = fpgm; |
| 15042 | 14738 | ||
| 14739 | if (getenv ("SFNT_FANCY_TEST")) | ||
| 14740 | { | ||
| 14741 | loca_long = NULL; | ||
| 14742 | loca_short = NULL; | ||
| 14743 | fancy = getenv ("SFNT_FANCY_TEST"); | ||
| 14744 | length = strlen (fancy); | ||
| 14745 | scale = sfnt_div_fixed (FANCY_PPEM, head->units_per_em); | ||
| 14746 | |||
| 14747 | if (hhea && maxp) | ||
| 14748 | hmtx = sfnt_read_hmtx_table (fd, font, hhea, maxp); | ||
| 14749 | |||
| 14750 | if (!maxp || !head || !prep || !hmtx || !hhea | ||
| 14751 | || table->num_subtables < 1) | ||
| 14752 | exit (1); | ||
| 14753 | |||
| 14754 | if (head->index_to_loc_format) | ||
| 14755 | { | ||
| 14756 | loca_long = sfnt_read_loca_table_long (fd, font); | ||
| 14757 | if (!loca_long) | ||
| 14758 | return 1; | ||
| 14759 | |||
| 14760 | fprintf (stderr, "long loca table has %zu glyphs\n", | ||
| 14761 | loca_long->num_offsets); | ||
| 14762 | } | ||
| 14763 | else | ||
| 14764 | { | ||
| 14765 | loca_short = sfnt_read_loca_table_short (fd, font); | ||
| 14766 | if (!loca_short) | ||
| 14767 | return 1; | ||
| 14768 | |||
| 14769 | fprintf (stderr, "short loca table has %zu glyphs\n", | ||
| 14770 | loca_short->num_offsets); | ||
| 14771 | } | ||
| 14772 | |||
| 14773 | interpreter = sfnt_make_interpreter (maxp, cvt, head, | ||
| 14774 | FANCY_PPEM, FANCY_PPEM); | ||
| 14775 | |||
| 14776 | if (!interpreter) | ||
| 14777 | exit (1); | ||
| 14778 | |||
| 14779 | if (fpgm) | ||
| 14780 | { | ||
| 14781 | fprintf (stderr, "interpreting the font program, with" | ||
| 14782 | " %zu instructions\n", fpgm->num_instructions); | ||
| 14783 | trap = sfnt_interpret_font_program (interpreter, fpgm); | ||
| 14784 | |||
| 14785 | if (trap) | ||
| 14786 | fprintf (stderr, "**TRAP**: %s\n", trap); | ||
| 14787 | } | ||
| 14788 | |||
| 14789 | if (prep) | ||
| 14790 | { | ||
| 14791 | fprintf (stderr, "interpreting the control value program, with" | ||
| 14792 | " %zu instructions\n", prep->num_instructions); | ||
| 14793 | trap = sfnt_interpret_control_value_program (interpreter, prep, | ||
| 14794 | &state); | ||
| 14795 | |||
| 14796 | if (trap) | ||
| 14797 | fprintf (stderr, "**TRAP**: %s\n", trap); | ||
| 14798 | } | ||
| 14799 | |||
| 14800 | state = interpreter->state; | ||
| 14801 | |||
| 14802 | advances = alloca (sizeof *advances * length); | ||
| 14803 | rasters = alloca (sizeof *rasters * length); | ||
| 14804 | |||
| 14805 | for (i = 0; i < length; ++i) | ||
| 14806 | { | ||
| 14807 | code = sfnt_lookup_glyph (fancy[i], data[0]); | ||
| 14808 | |||
| 14809 | if (!code) | ||
| 14810 | exit (2); | ||
| 14811 | |||
| 14812 | glyph = sfnt_read_glyph (code, glyf, loca_short, | ||
| 14813 | loca_long); | ||
| 14814 | |||
| 14815 | if (!glyph || !glyph->simple) | ||
| 14816 | exit (3); | ||
| 14817 | |||
| 14818 | if (sfnt_lookup_glyph_metrics (code, -1, | ||
| 14819 | &metrics, | ||
| 14820 | hmtx, hhea, | ||
| 14821 | head, maxp)) | ||
| 14822 | exit (4); | ||
| 14823 | |||
| 14824 | interpreter->state = state; | ||
| 14825 | trap = sfnt_interpret_simple_glyph (glyph, interpreter, | ||
| 14826 | &metrics, &value); | ||
| 14827 | |||
| 14828 | if (trap) | ||
| 14829 | { | ||
| 14830 | fprintf (stderr, "*TRAP*: %s\n", trap); | ||
| 14831 | exit (5); | ||
| 14832 | } | ||
| 14833 | |||
| 14834 | outline = sfnt_build_instructed_outline (value); | ||
| 14835 | |||
| 14836 | if (!outline) | ||
| 14837 | exit (6); | ||
| 14838 | |||
| 14839 | xfree (value); | ||
| 14840 | |||
| 14841 | raster = sfnt_raster_glyph_outline (outline); | ||
| 14842 | |||
| 14843 | if (!raster) | ||
| 14844 | exit (7); | ||
| 14845 | |||
| 14846 | xfree (outline); | ||
| 14847 | |||
| 14848 | rasters[i] = raster; | ||
| 14849 | advances[i] = sfnt_mul_fixed (metrics.advance, scale); | ||
| 14850 | } | ||
| 14851 | |||
| 14852 | sfnt_x_raster (rasters, advances, length, hhea, scale); | ||
| 14853 | exit (0); | ||
| 14854 | } | ||
| 14855 | |||
| 15043 | if (head && maxp && maxp->version >= 0x00010000) | 14856 | if (head && maxp && maxp->version >= 0x00010000) |
| 15044 | { | 14857 | { |
| 15045 | fprintf (stderr, "creating interpreter\n" | 14858 | fprintf (stderr, "creating interpreter\n" |
| @@ -15057,7 +14870,8 @@ main (int argc, char **argv) | |||
| 15057 | cvt ? cvt->num_elements : 0ul); | 14870 | cvt ? cvt->num_elements : 0ul); |
| 15058 | 14871 | ||
| 15059 | interpreter = sfnt_make_interpreter (maxp, cvt, head, | 14872 | interpreter = sfnt_make_interpreter (maxp, cvt, head, |
| 15060 | 20, 20); | 14873 | FANCY_PPEM, |
| 14874 | FANCY_PPEM); | ||
| 15061 | state = interpreter->state; | 14875 | state = interpreter->state; |
| 15062 | 14876 | ||
| 15063 | if (fpgm) | 14877 | if (fpgm) |
| @@ -15210,6 +15024,7 @@ main (int argc, char **argv) | |||
| 15210 | 15024 | ||
| 15211 | if ((loca_long || loca_short) && glyf) | 15025 | if ((loca_long || loca_short) && glyf) |
| 15212 | { | 15026 | { |
| 15027 | scale = sfnt_div_fixed (EASY_PPEM, head->units_per_em); | ||
| 15213 | glyph = sfnt_read_glyph (code, glyf, loca_short, | 15028 | glyph = sfnt_read_glyph (code, glyf, loca_short, |
| 15214 | loca_long); | 15029 | loca_long); |
| 15215 | 15030 | ||
| @@ -15233,7 +15048,7 @@ main (int argc, char **argv) | |||
| 15233 | /* Time this important bit. */ | 15048 | /* Time this important bit. */ |
| 15234 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); | 15049 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); |
| 15235 | outline = sfnt_build_glyph_outline (glyph, head, | 15050 | outline = sfnt_build_glyph_outline (glyph, head, |
| 15236 | 20, | 15051 | EASY_PPEM, |
| 15237 | sfnt_test_get_glyph, | 15052 | sfnt_test_get_glyph, |
| 15238 | sfnt_test_free_glyph, | 15053 | sfnt_test_free_glyph, |
| 15239 | &dcontext); | 15054 | &dcontext); |
| @@ -15275,7 +15090,7 @@ main (int argc, char **argv) | |||
| 15275 | 15090 | ||
| 15276 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); | 15091 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); |
| 15277 | 15092 | ||
| 15278 | for (i = 0; i < 400; ++i) | 15093 | for (i = 0; i < 120; ++i) |
| 15279 | { | 15094 | { |
| 15280 | xfree (raster); | 15095 | xfree (raster); |
| 15281 | raster = sfnt_raster_glyph_outline (outline); | 15096 | raster = sfnt_raster_glyph_outline (outline); |
| @@ -15285,7 +15100,7 @@ main (int argc, char **argv) | |||
| 15285 | sub2 = timespec_sub (end, start); | 15100 | sub2 = timespec_sub (end, start); |
| 15286 | 15101 | ||
| 15287 | /* Print out the raster. */ | 15102 | /* Print out the raster. */ |
| 15288 | sfnt_test_raster (raster); | 15103 | sfnt_test_raster (raster, hhea, scale); |
| 15289 | printf ("raster offsets: %d, %d\n", | 15104 | printf ("raster offsets: %d, %d\n", |
| 15290 | raster->offx, raster->offy); | 15105 | raster->offx, raster->offy); |
| 15291 | 15106 | ||
| @@ -15300,7 +15115,7 @@ main (int argc, char **argv) | |||
| 15300 | 15115 | ||
| 15301 | if (hmtx && head) | 15116 | if (hmtx && head) |
| 15302 | { | 15117 | { |
| 15303 | if (!sfnt_lookup_glyph_metrics (code, 20, | 15118 | if (!sfnt_lookup_glyph_metrics (code, EASY_PPEM, |
| 15304 | &metrics, | 15119 | &metrics, |
| 15305 | hmtx, hhea, | 15120 | hmtx, hhea, |
| 15306 | head, maxp)) | 15121 | head, maxp)) |
| @@ -15320,10 +15135,10 @@ main (int argc, char **argv) | |||
| 15320 | } | 15135 | } |
| 15321 | 15136 | ||
| 15322 | if (glyph->simple | 15137 | if (glyph->simple |
| 15323 | && sfnt_lookup_glyph_metrics (code, -1, | 15138 | && !sfnt_lookup_glyph_metrics (code, -1, |
| 15324 | &metrics, | 15139 | &metrics, |
| 15325 | hmtx, hhea, | 15140 | hmtx, hhea, |
| 15326 | head, maxp)) | 15141 | head, maxp)) |
| 15327 | { | 15142 | { |
| 15328 | printf ("interpreting glyph\n"); | 15143 | printf ("interpreting glyph\n"); |
| 15329 | interpreter->state = state; | 15144 | interpreter->state = state; |
| @@ -15349,7 +15164,9 @@ main (int argc, char **argv) | |||
| 15349 | 15164 | ||
| 15350 | if (raster) | 15165 | if (raster) |
| 15351 | { | 15166 | { |
| 15352 | sfnt_test_raster (raster); | 15167 | sfnt_test_raster (raster, hhea, scale); |
| 15168 | printf ("raster offsets: %d, %d\n", | ||
| 15169 | raster->offx, raster->offy); | ||
| 15353 | xfree (raster); | 15170 | xfree (raster); |
| 15354 | } | 15171 | } |
| 15355 | } | 15172 | } |
| @@ -15368,7 +15185,7 @@ main (int argc, char **argv) | |||
| 15368 | printf ("time spent building edges: %lld sec %ld nsec\n", | 15185 | printf ("time spent building edges: %lld sec %ld nsec\n", |
| 15369 | (long long) sub1.tv_sec, sub1.tv_nsec); | 15186 | (long long) sub1.tv_sec, sub1.tv_nsec); |
| 15370 | printf ("time spent rasterizing: %lld sec %ld nsec\n", | 15187 | printf ("time spent rasterizing: %lld sec %ld nsec\n", |
| 15371 | (long long) sub2.tv_sec / 400, sub2.tv_nsec / 400); | 15188 | (long long) sub2.tv_sec / 120, sub2.tv_nsec / 120); |
| 15372 | 15189 | ||
| 15373 | xfree (outline); | 15190 | xfree (outline); |
| 15374 | } | 15191 | } |
diff --git a/src/sfnt.h b/src/sfnt.h index 409c45085ba..0845cb5be51 100644 --- a/src/sfnt.h +++ b/src/sfnt.h | |||
| @@ -23,6 +23,11 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| 23 | 23 | ||
| 24 | #include <stdint.h> | 24 | #include <stdint.h> |
| 25 | #include <stddef.h> | 25 | #include <stddef.h> |
| 26 | #include <setjmp.h> | ||
| 27 | |||
| 28 | #if defined emacs || defined TEST | ||
| 29 | #define SFNT_ENABLE_HINTING | ||
| 30 | #endif | ||
| 26 | 31 | ||
| 27 | 32 | ||
| 28 | 33 | ||
| @@ -719,7 +724,7 @@ struct sfnt_edge | |||
| 719 | 724 | ||
| 720 | enum | 725 | enum |
| 721 | { | 726 | { |
| 722 | SFNT_POLY_SHIFT = 2, | 727 | SFNT_POLY_SHIFT = 3, |
| 723 | SFNT_POLY_SAMPLE = (1 << SFNT_POLY_SHIFT), | 728 | SFNT_POLY_SAMPLE = (1 << SFNT_POLY_SHIFT), |
| 724 | SFNT_POLY_MASK = (SFNT_POLY_SAMPLE - 1), | 729 | SFNT_POLY_MASK = (SFNT_POLY_SAMPLE - 1), |
| 725 | SFNT_POLY_STEP = (0x10000 >> SFNT_POLY_SHIFT), | 730 | SFNT_POLY_STEP = (0x10000 >> SFNT_POLY_SHIFT), |
| @@ -984,6 +989,9 @@ extern int sfnt_lookup_glyph_metrics (sfnt_glyph, int, | |||
| 984 | struct sfnt_head_table *, | 989 | struct sfnt_head_table *, |
| 985 | struct sfnt_maxp_table *); | 990 | struct sfnt_maxp_table *); |
| 986 | 991 | ||
| 992 | extern void sfnt_scale_metrics (struct sfnt_glyph_metrics *, | ||
| 993 | sfnt_fixed); | ||
| 994 | |||
| 987 | #define PROTOTYPE int, struct sfnt_offset_subtable * | 995 | #define PROTOTYPE int, struct sfnt_offset_subtable * |
| 988 | extern struct sfnt_name_table *sfnt_read_name_table (PROTOTYPE); | 996 | extern struct sfnt_name_table *sfnt_read_name_table (PROTOTYPE); |
| 989 | #undef PROTOTYPE | 997 | #undef PROTOTYPE |
| @@ -1003,4 +1011,477 @@ extern char *sfnt_find_metadata (struct sfnt_meta_table *, | |||
| 1003 | extern struct sfnt_ttc_header *sfnt_read_ttc_header (int); | 1011 | extern struct sfnt_ttc_header *sfnt_read_ttc_header (int); |
| 1004 | 1012 | ||
| 1005 | #endif /* TEST */ | 1013 | #endif /* TEST */ |
| 1014 | |||
| 1015 | |||
| 1016 | |||
| 1017 | /* TrueType hinting support. */ | ||
| 1018 | |||
| 1019 | #ifdef SFNT_ENABLE_HINTING | ||
| 1020 | |||
| 1021 | /* Structure definitions for tables used by the TrueType | ||
| 1022 | interpreter. */ | ||
| 1023 | |||
| 1024 | struct sfnt_cvt_table | ||
| 1025 | { | ||
| 1026 | /* Number of elements in the control value table. */ | ||
| 1027 | size_t num_elements; | ||
| 1028 | |||
| 1029 | /* Pointer to elements in the control value table. */ | ||
| 1030 | sfnt_fword *values; | ||
| 1031 | }; | ||
| 1032 | |||
| 1033 | struct sfnt_fpgm_table | ||
| 1034 | { | ||
| 1035 | /* Number of instructions in the font program table. */ | ||
| 1036 | size_t num_instructions; | ||
| 1037 | |||
| 1038 | /* Pointer to elements in the font program table. */ | ||
| 1039 | unsigned char *instructions; | ||
| 1040 | }; | ||
| 1041 | |||
| 1042 | struct sfnt_prep_table | ||
| 1043 | { | ||
| 1044 | /* Number of instructions in the control value program (pre-program) | ||
| 1045 | table. */ | ||
| 1046 | size_t num_instructions; | ||
| 1047 | |||
| 1048 | /* Pointer to elements in the preprogram table. */ | ||
| 1049 | unsigned char *instructions; | ||
| 1050 | }; | ||
| 1051 | |||
| 1052 | |||
| 1053 | |||
| 1054 | /* Fixed point types used by the TrueType interpreter. */ | ||
| 1055 | |||
| 1056 | /* 26.6 fixed point type used within the interpreter. */ | ||
| 1057 | typedef int32_t sfnt_f26dot6; | ||
| 1058 | |||
| 1059 | /* 2.14 fixed point type used to represent versors of unit | ||
| 1060 | vectors. */ | ||
| 1061 | typedef int16_t sfnt_f2dot14; | ||
| 1062 | |||
| 1063 | /* 18.14 fixed point type used to calculate rounding details. */ | ||
| 1064 | typedef int32_t sfnt_f18dot14; | ||
| 1065 | |||
| 1066 | |||
| 1067 | |||
| 1068 | /* Interpreter execution environment. */ | ||
| 1069 | |||
| 1070 | struct sfnt_unit_vector | ||
| 1071 | { | ||
| 1072 | /* X and Y versors of the 2d unit vector. */ | ||
| 1073 | sfnt_f2dot14 x, y; | ||
| 1074 | }; | ||
| 1075 | |||
| 1076 | struct sfnt_interpreter_definition | ||
| 1077 | { | ||
| 1078 | /* The opcode of this instruction or function. */ | ||
| 1079 | uint16_t opcode; | ||
| 1080 | |||
| 1081 | /* The number of instructions. */ | ||
| 1082 | uint16_t instruction_count; | ||
| 1083 | |||
| 1084 | /* Pointer to instructions belonging to the definition. This | ||
| 1085 | pointer points directly into the control value or font program. | ||
| 1086 | Make sure both programs are kept around as long as the | ||
| 1087 | interpreter continues to exist. */ | ||
| 1088 | unsigned char *instructions; | ||
| 1089 | }; | ||
| 1090 | |||
| 1091 | /* This structure represents a ``struct sfnt_glyph'' that has been | ||
| 1092 | scaled to a given pixel size. | ||
| 1093 | |||
| 1094 | It can either contain a simple glyph, or a decomposed compound | ||
| 1095 | glyph; instructions are interpreted for both simple glyphs, simple | ||
| 1096 | glyph components inside a compound glyph, and compound glyphs as a | ||
| 1097 | whole. | ||
| 1098 | |||
| 1099 | In addition to the glyph data itself, it also records various | ||
| 1100 | information for the instruction interpretation process: | ||
| 1101 | |||
| 1102 | - ``current'' point coordinates, which have been modified | ||
| 1103 | by the instructing process. | ||
| 1104 | |||
| 1105 | - two phantom points at the origin and the advance of the | ||
| 1106 | glyph. */ | ||
| 1107 | |||
| 1108 | struct sfnt_interpreter_zone | ||
| 1109 | { | ||
| 1110 | /* The number of points in this zone, including the two phantom | ||
| 1111 | points at the end. */ | ||
| 1112 | size_t num_points; | ||
| 1113 | |||
| 1114 | /* The number of contours in this zone. */ | ||
| 1115 | size_t num_contours; | ||
| 1116 | |||
| 1117 | /* The end points of each contour. */ | ||
| 1118 | size_t *contour_end_points; | ||
| 1119 | |||
| 1120 | /* Pointer to the X axis point data. */ | ||
| 1121 | sfnt_f26dot6 *restrict x_points; | ||
| 1122 | |||
| 1123 | /* Pointer to the X axis current point data. */ | ||
| 1124 | sfnt_f26dot6 *restrict x_current; | ||
| 1125 | |||
| 1126 | /* Pointer to the Y axis point data. */ | ||
| 1127 | sfnt_f26dot6 *restrict y_points; | ||
| 1128 | |||
| 1129 | /* Pointer to the Y axis current point data. */ | ||
| 1130 | sfnt_f26dot6 *restrict y_current; | ||
| 1131 | |||
| 1132 | /* Pointer to the flags associated with this data. */ | ||
| 1133 | unsigned char *flags; | ||
| 1134 | }; | ||
| 1135 | |||
| 1136 | enum | ||
| 1137 | { | ||
| 1138 | /* Bits 7 and 6 of a glyph point's flags is reserved. This scaler | ||
| 1139 | uses it to mean that the point has been touched in one axis or | ||
| 1140 | another. */ | ||
| 1141 | SFNT_POINT_TOUCHED_X = (1 << 7), | ||
| 1142 | SFNT_POINT_TOUCHED_Y = (1 << 6), | ||
| 1143 | SFNT_POINT_TOUCHED_BOTH = (SFNT_POINT_TOUCHED_X | ||
| 1144 | | SFNT_POINT_TOUCHED_Y), | ||
| 1145 | }; | ||
| 1146 | |||
| 1147 | /* This is needed because `round' below needs an interpreter | ||
| 1148 | argument. */ | ||
| 1149 | struct sfnt_interpreter; | ||
| 1150 | |||
| 1151 | struct sfnt_graphics_state | ||
| 1152 | { | ||
| 1153 | /* Pointer to the function used for rounding. This function is | ||
| 1154 | asymmetric, so -0.5 rounds up to 0, not -1. It is up to the | ||
| 1155 | caller to handle negative values. | ||
| 1156 | |||
| 1157 | Value is undefined unless sfnt_validate_gs has been called, and | ||
| 1158 | the second argument may be used to provide detailed rounding | ||
| 1159 | information (``super rounding state''.) */ | ||
| 1160 | sfnt_f26dot6 (*round) (sfnt_f26dot6, struct sfnt_interpreter *); | ||
| 1161 | |||
| 1162 | /* Pointer to the function used to project euclidean vectors onto | ||
| 1163 | the projection vector. Value is the magnitude of the projected | ||
| 1164 | vector. */ | ||
| 1165 | sfnt_f26dot6 (*project) (sfnt_f26dot6, sfnt_f26dot6, | ||
| 1166 | struct sfnt_interpreter *); | ||
| 1167 | |||
| 1168 | /* Pointer to the function used to project euclidean vectors onto | ||
| 1169 | the dual projection vector. Value is the magnitude of the | ||
| 1170 | projected vector. */ | ||
| 1171 | sfnt_f26dot6 (*dual_project) (sfnt_f26dot6, sfnt_f26dot6, | ||
| 1172 | struct sfnt_interpreter *); | ||
| 1173 | |||
| 1174 | /* Pointer to the function used to move specified points | ||
| 1175 | along the freedom vector by a distance specified in terms | ||
| 1176 | of the projection vector. */ | ||
| 1177 | void (*move) (sfnt_f26dot6 *restrict, | ||
| 1178 | sfnt_f26dot6 *restrict, size_t, | ||
| 1179 | struct sfnt_interpreter *, | ||
| 1180 | sfnt_f26dot6, unsigned char *); | ||
| 1181 | |||
| 1182 | /* Dot product between the freedom and the projection vectors. */ | ||
| 1183 | sfnt_f2dot14 vector_dot_product; | ||
| 1184 | |||
| 1185 | /* Controls whether the sign of control value table entries will be | ||
| 1186 | changed to match the sign of the actual distance measurement with | ||
| 1187 | which it is compared. Setting auto flip to TRUE makes it | ||
| 1188 | possible to control distances measured with or against the | ||
| 1189 | projection vector with a single control value table entry. When | ||
| 1190 | auto flip is set to FALSE, distances must be measured with the | ||
| 1191 | projection vector. */ | ||
| 1192 | bool auto_flip; | ||
| 1193 | |||
| 1194 | /* Limits the regularizing effects of control value table entries to | ||
| 1195 | cases where the difference between the table value and the | ||
| 1196 | measurement taken from the original outline is sufficiently | ||
| 1197 | small. */ | ||
| 1198 | sfnt_f26dot6 cvt_cut_in; | ||
| 1199 | |||
| 1200 | /* Establishes the base value used to calculate the range of point | ||
| 1201 | sizes to which a given DELTAC[] or DELTAP[] instruction will | ||
| 1202 | apply. The formulas given below are used to calculate the range | ||
| 1203 | of the various DELTA instructions. | ||
| 1204 | |||
| 1205 | DELTAC1 DELTAP1 (delta_base) through (delta_base + 15) | ||
| 1206 | DELTAC2 DELTAP2 (delta_base + 16) through (delta_base + 31) | ||
| 1207 | DELTAC3 DELTAP3 (delta_base + 32) through (delta_base + 47) | ||
| 1208 | |||
| 1209 | Please keep this documentation in sync with the TrueType | ||
| 1210 | reference manual. */ | ||
| 1211 | unsigned short delta_base; | ||
| 1212 | |||
| 1213 | /* Determines the range of movement and smallest magnitude of | ||
| 1214 | movement (the step) in a DELTAC[] or DELTAP[] instruction. | ||
| 1215 | Changing the value of the delta shift makes it possible to trade | ||
| 1216 | off fine control of point movement for range of movement. A low | ||
| 1217 | delta shift favors range of movement over fine control. A high | ||
| 1218 | delta shift favors fine control over range of movement. The step | ||
| 1219 | has the value 1/2 to the power delta shift. The range of | ||
| 1220 | movement is calculated by taking the number of steps allowed (16) | ||
| 1221 | and multiplying it by the step. | ||
| 1222 | |||
| 1223 | The legal range for delta shift is zero through six. Negative | ||
| 1224 | values are illegal. */ | ||
| 1225 | unsigned short delta_shift; | ||
| 1226 | |||
| 1227 | /* A second projection vector set to a line defined by the original | ||
| 1228 | outline location of two points. The dual projection vector is | ||
| 1229 | used when it is necessary to measure distances from the scaled | ||
| 1230 | outline before any instructions were executed. */ | ||
| 1231 | struct sfnt_unit_vector dual_projection_vector; | ||
| 1232 | |||
| 1233 | /* A unit vector that establishes an axis along which points can | ||
| 1234 | move. */ | ||
| 1235 | struct sfnt_unit_vector freedom_vector; | ||
| 1236 | |||
| 1237 | /* Makes it possible to turn off instructions under some | ||
| 1238 | circumstances. When flag 1 is set, changes to the graphics state | ||
| 1239 | made in the control value program will be ignored. When flag is | ||
| 1240 | 1, grid fitting instructions will be ignored. */ | ||
| 1241 | unsigned char instruct_control; | ||
| 1242 | |||
| 1243 | /* Makes it possible to repeat certain instructions a designated | ||
| 1244 | number of times. The default value of one assures that unless | ||
| 1245 | the value of loop is altered, these instructions will execute one | ||
| 1246 | time. */ | ||
| 1247 | unsigned short loop; | ||
| 1248 | |||
| 1249 | /* Establishes the smallest possible value to which a distance will | ||
| 1250 | be rounded. */ | ||
| 1251 | sfnt_f26dot6 minimum_distance; | ||
| 1252 | |||
| 1253 | /* A unit vector whose direction establishes an axis along which | ||
| 1254 | distances are measured. */ | ||
| 1255 | struct sfnt_unit_vector projection_vector; | ||
| 1256 | |||
| 1257 | /* Determines the manner in which values are rounded. Can be set to | ||
| 1258 | a number of predefined states or to a customized state with the | ||
| 1259 | SROUND or S45ROUND instructions. */ | ||
| 1260 | int round_state; | ||
| 1261 | |||
| 1262 | /* Reference points. These reference point numbers, which together | ||
| 1263 | with a zone designation, specify a point in either the glyph zone | ||
| 1264 | or the twilight zone. */ | ||
| 1265 | uint16_t rp0, rp1, rp2; | ||
| 1266 | |||
| 1267 | /* Flags which determine whether the interpreter will activate | ||
| 1268 | dropout control for the current glyph. */ | ||
| 1269 | int scan_control; | ||
| 1270 | |||
| 1271 | /* The distance difference below which the interpreter will replace | ||
| 1272 | a CVT distance or an actual distance in favor of the single width | ||
| 1273 | value. */ | ||
| 1274 | sfnt_f26dot6 sw_cut_in; | ||
| 1275 | |||
| 1276 | /* The value used in place of the control value table distance or | ||
| 1277 | the actual distance value when the difference between that | ||
| 1278 | distance and the single width value is less than the single width | ||
| 1279 | cut-in. */ | ||
| 1280 | sfnt_f26dot6 single_width_value; | ||
| 1281 | |||
| 1282 | /* Zone pointers, which reference a zone. */ | ||
| 1283 | int zp0, zp1, zp2; | ||
| 1284 | }; | ||
| 1285 | |||
| 1286 | struct sfnt_interpreter | ||
| 1287 | { | ||
| 1288 | /* The number of elements in the stack. */ | ||
| 1289 | uint16_t max_stack_elements; | ||
| 1290 | |||
| 1291 | /* The number of instructions in INSTRUCTIONS. */ | ||
| 1292 | uint16_t num_instructions; | ||
| 1293 | |||
| 1294 | /* Size of the storage area. */ | ||
| 1295 | uint16_t storage_size; | ||
| 1296 | |||
| 1297 | /* Size of the function definition area. */ | ||
| 1298 | uint16_t function_defs_size; | ||
| 1299 | |||
| 1300 | /* Size of the instruction definition area. */ | ||
| 1301 | uint16_t instruction_defs_size; | ||
| 1302 | |||
| 1303 | /* Size of the twilight zone. */ | ||
| 1304 | uint16_t twilight_zone_size; | ||
| 1305 | |||
| 1306 | /* The instruction pointer. This points to the instruction | ||
| 1307 | currently being executed. */ | ||
| 1308 | int IP; | ||
| 1309 | |||
| 1310 | /* The current scale. */ | ||
| 1311 | sfnt_fixed scale; | ||
| 1312 | |||
| 1313 | /* The current ppem and point size. */ | ||
| 1314 | int ppem, point_size; | ||
| 1315 | |||
| 1316 | /* The execution stack. This has at most max_stack_elements | ||
| 1317 | elements. */ | ||
| 1318 | uint32_t *stack; | ||
| 1319 | |||
| 1320 | /* Pointer past the top of the stack. */ | ||
| 1321 | uint32_t *SP; | ||
| 1322 | |||
| 1323 | /* The size of the control value table. */ | ||
| 1324 | size_t cvt_size; | ||
| 1325 | |||
| 1326 | /* Pointer to instructions currently being executed. */ | ||
| 1327 | unsigned char *restrict instructions; | ||
| 1328 | |||
| 1329 | /* The twilight zone. May not be NULL. */ | ||
| 1330 | sfnt_f26dot6 *restrict twilight_x, *restrict twilight_y; | ||
| 1331 | |||
| 1332 | /* The original X positions of points in the twilight zone. */ | ||
| 1333 | sfnt_f26dot6 *restrict twilight_original_x; | ||
| 1334 | |||
| 1335 | /* The original Y positions of points in the twilight zone. | ||
| 1336 | |||
| 1337 | Apple does not directly say whether or not points in the twilight | ||
| 1338 | zone can have their original positions changed. But this is | ||
| 1339 | implied by ``create points in the twilight zone''. */ | ||
| 1340 | sfnt_f26dot6 *restrict twilight_original_y; | ||
| 1341 | |||
| 1342 | /* The scaled outlines being manipulated. May be NULL. */ | ||
| 1343 | struct sfnt_interpreter_zone *glyph_zone; | ||
| 1344 | |||
| 1345 | /* The glyph advance width. Value is undefined unless GLYPH_ZONE is | ||
| 1346 | set. */ | ||
| 1347 | sfnt_f26dot6 advance_width; | ||
| 1348 | |||
| 1349 | /* The storage area. */ | ||
| 1350 | uint32_t *storage; | ||
| 1351 | |||
| 1352 | /* Control value table values. */ | ||
| 1353 | sfnt_f26dot6 *cvt; | ||
| 1354 | |||
| 1355 | /* Function definitions. */ | ||
| 1356 | struct sfnt_interpreter_definition *function_defs; | ||
| 1357 | |||
| 1358 | /* Instruction definitions. */ | ||
| 1359 | struct sfnt_interpreter_definition *instruction_defs; | ||
| 1360 | |||
| 1361 | /* Interpreter registers. */ | ||
| 1362 | struct sfnt_graphics_state state; | ||
| 1363 | |||
| 1364 | /* Detailed rounding state used when state.round_state indicates | ||
| 1365 | that fine grained rounding should be used. | ||
| 1366 | |||
| 1367 | PERIOD says how often a round value occurs, for numbers | ||
| 1368 | increasing from PHASE to infinity. | ||
| 1369 | |||
| 1370 | THRESHOLD says when to round a value between two increasing | ||
| 1371 | periods towards the larger period. */ | ||
| 1372 | sfnt_f26dot6 period, phase, threshold; | ||
| 1373 | |||
| 1374 | /* The depth of any ongoing calls. */ | ||
| 1375 | int call_depth; | ||
| 1376 | |||
| 1377 | /* Jump buffer for traps. */ | ||
| 1378 | jmp_buf trap; | ||
| 1379 | |||
| 1380 | /* What was the trap. */ | ||
| 1381 | const char *trap_reason; | ||
| 1382 | |||
| 1383 | #ifdef TEST | ||
| 1384 | /* If non-NULL, function called before each instruction is | ||
| 1385 | executed. */ | ||
| 1386 | void (*run_hook) (struct sfnt_interpreter *); | ||
| 1387 | |||
| 1388 | /* If non-NULL, function called before each stack element is | ||
| 1389 | pushed. */ | ||
| 1390 | void (*push_hook) (struct sfnt_interpreter *, uint32_t); | ||
| 1391 | |||
| 1392 | /* If non-NULL, function called before each stack element is | ||
| 1393 | popped. */ | ||
| 1394 | void (*pop_hook) (struct sfnt_interpreter *, uint32_t); | ||
| 1395 | #endif | ||
| 1396 | }; | ||
| 1397 | |||
| 1398 | |||
| 1399 | |||
| 1400 | /* Glyph hinting. */ | ||
| 1401 | |||
| 1402 | /* Structure describing a single scaled and fitted outline. */ | ||
| 1403 | |||
| 1404 | struct sfnt_instructed_outline | ||
| 1405 | { | ||
| 1406 | /* The number of points in this contour, including the two phantom | ||
| 1407 | points at the end. */ | ||
| 1408 | size_t num_points; | ||
| 1409 | |||
| 1410 | /* The number of contours in this outline. */ | ||
| 1411 | size_t num_contours; | ||
| 1412 | |||
| 1413 | /* The end points of each contour. */ | ||
| 1414 | size_t *contour_end_points; | ||
| 1415 | |||
| 1416 | /* The points of each contour, with two additional phantom points at | ||
| 1417 | the end. */ | ||
| 1418 | sfnt_f26dot6 *restrict x_points, *restrict y_points; | ||
| 1419 | |||
| 1420 | /* The flags of each point. */ | ||
| 1421 | unsigned char *flags; | ||
| 1422 | }; | ||
| 1423 | |||
| 1424 | |||
| 1425 | |||
| 1426 | /* Functions used to read tables used by the TrueType interpreter. */ | ||
| 1427 | |||
| 1428 | #ifndef TEST | ||
| 1429 | |||
| 1430 | #define PROTOTYPE int, struct sfnt_offset_subtable * | ||
| 1431 | |||
| 1432 | extern struct sfnt_cvt_table *sfnt_read_cvt_table (PROTOTYPE); | ||
| 1433 | extern struct sfnt_fpgm_table *sfnt_read_fpgm_table (PROTOTYPE); | ||
| 1434 | extern struct sfnt_prep_table *sfnt_read_prep_table (PROTOTYPE); | ||
| 1435 | |||
| 1436 | #undef PROTOTYPE | ||
| 1437 | |||
| 1438 | #define PROTOTYPE \ | ||
| 1439 | struct sfnt_maxp_table *, \ | ||
| 1440 | struct sfnt_cvt_table *, \ | ||
| 1441 | struct sfnt_head_table *, \ | ||
| 1442 | int, int | ||
| 1443 | |||
| 1444 | extern struct sfnt_interpreter *sfnt_make_interpreter (PROTOTYPE); | ||
| 1445 | |||
| 1446 | #undef PROTOTYPE | ||
| 1447 | |||
| 1448 | #define PROTOTYPE \ | ||
| 1449 | struct sfnt_interpreter *, \ | ||
| 1450 | struct sfnt_fpgm_table * | ||
| 1451 | |||
| 1452 | extern const char *sfnt_interpret_font_program (PROTOTYPE); | ||
| 1453 | |||
| 1454 | #undef PROTOTYPE | ||
| 1455 | |||
| 1456 | #define PROTOTYPE \ | ||
| 1457 | struct sfnt_interpreter *, \ | ||
| 1458 | struct sfnt_prep_table *, \ | ||
| 1459 | struct sfnt_graphics_state * | ||
| 1460 | |||
| 1461 | extern const char *sfnt_interpret_control_value_program (PROTOTYPE); | ||
| 1462 | |||
| 1463 | #undef PROTOTYPE | ||
| 1464 | |||
| 1465 | #define PROTOTYPE struct sfnt_instructed_outline * | ||
| 1466 | |||
| 1467 | extern struct sfnt_glyph_outline *sfnt_build_instructed_outline (PROTOTYPE); | ||
| 1468 | |||
| 1469 | #undef PROTOTYPE | ||
| 1470 | |||
| 1471 | #define PROTOTYPE \ | ||
| 1472 | struct sfnt_glyph *, \ | ||
| 1473 | struct sfnt_interpreter *, \ | ||
| 1474 | struct sfnt_glyph_metrics *, \ | ||
| 1475 | struct sfnt_instructed_outline ** | ||
| 1476 | |||
| 1477 | extern const char *sfnt_interpret_simple_glyph (PROTOTYPE); | ||
| 1478 | |||
| 1479 | #undef PROTOTYPE | ||
| 1480 | |||
| 1481 | #endif /* TEST */ | ||
| 1482 | |||
| 1483 | |||
| 1484 | |||
| 1485 | #endif /* SFNT_ENABLE_HINTING */ | ||
| 1486 | |||
| 1006 | #endif /* _SFNT_H_ */ | 1487 | #endif /* _SFNT_H_ */ |
diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c index d8f598fd330..feea92827d9 100644 --- a/src/sfntfont-android.c +++ b/src/sfntfont-android.c | |||
| @@ -454,7 +454,7 @@ sfntfont_android_put_glyphs (struct glyph_string *s, int from, | |||
| 454 | { | 454 | { |
| 455 | text.x1 = x_coords[0] + rasters[0]->offx; | 455 | text.x1 = x_coords[0] + rasters[0]->offx; |
| 456 | text.x2 = text.x1 + rasters[0]->width; | 456 | text.x2 = text.x1 + rasters[0]->width; |
| 457 | text.y1 = y - (rasters[0]->height + rasters[0]->offy); | 457 | text.y1 = y - rasters[0]->height - rasters[0]->offy; |
| 458 | text.y2 = y - rasters[0]->offy; | 458 | text.y2 = y - rasters[0]->offy; |
| 459 | } | 459 | } |
| 460 | else | 460 | else |
| @@ -469,7 +469,7 @@ sfntfont_android_put_glyphs (struct glyph_string *s, int from, | |||
| 469 | 469 | ||
| 470 | character.x1 = x_coords[i] + rasters[i]->offx; | 470 | character.x1 = x_coords[i] + rasters[i]->offx; |
| 471 | character.x2 = character.x1 + rasters[i]->width; | 471 | character.x2 = character.x1 + rasters[i]->width; |
| 472 | character.y1 = y - (rasters[i]->height + rasters[i]->offy); | 472 | character.y1 = y - rasters[i]->height - rasters[i]->offy; |
| 473 | character.y2 = y - rasters[i]->offy; | 473 | character.y2 = y - rasters[i]->offy; |
| 474 | 474 | ||
| 475 | sfntfont_android_union_boxes (text, character, &text); | 475 | sfntfont_android_union_boxes (text, character, &text); |
diff --git a/src/sfntfont.c b/src/sfntfont.c index d9b152e27eb..dbd1a037f4a 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c | |||
| @@ -1456,6 +1456,9 @@ sfntfont_dereference_outline (struct sfnt_glyph_outline *outline) | |||
| 1456 | Use the offset information in the long or short loca tables | 1456 | Use the offset information in the long or short loca tables |
| 1457 | LOCA_LONG and LOCA_SHORT, whichever is set. | 1457 | LOCA_LONG and LOCA_SHORT, whichever is set. |
| 1458 | 1458 | ||
| 1459 | If INTERPRETER is non-NULL, then possibly use the unscaled glyph | ||
| 1460 | metrics in METRICS when instructing the glyph. | ||
| 1461 | |||
| 1459 | Return the outline with an incremented reference count and enter | 1462 | Return the outline with an incremented reference count and enter |
| 1460 | the generated outline into CACHE upon success, possibly discarding | 1463 | the generated outline into CACHE upon success, possibly discarding |
| 1461 | any older outlines, or NULL on failure. */ | 1464 | any older outlines, or NULL on failure. */ |
| @@ -1467,12 +1470,16 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code, | |||
| 1467 | struct sfnt_glyf_table *glyf, | 1470 | struct sfnt_glyf_table *glyf, |
| 1468 | struct sfnt_head_table *head, | 1471 | struct sfnt_head_table *head, |
| 1469 | struct sfnt_loca_table_short *loca_short, | 1472 | struct sfnt_loca_table_short *loca_short, |
| 1470 | struct sfnt_loca_table_long *loca_long) | 1473 | struct sfnt_loca_table_long *loca_long, |
| 1474 | struct sfnt_interpreter *interpreter, | ||
| 1475 | struct sfnt_glyph_metrics *metrics) | ||
| 1471 | { | 1476 | { |
| 1472 | struct sfnt_outline_cache *start; | 1477 | struct sfnt_outline_cache *start; |
| 1473 | struct sfnt_glyph_outline *outline; | 1478 | struct sfnt_glyph_outline *outline; |
| 1474 | struct sfnt_glyph *glyph; | 1479 | struct sfnt_glyph *glyph; |
| 1475 | struct sfntfont_get_glyph_outline_dcontext dcontext; | 1480 | struct sfntfont_get_glyph_outline_dcontext dcontext; |
| 1481 | struct sfnt_instructed_outline *value; | ||
| 1482 | const char *error; | ||
| 1476 | 1483 | ||
| 1477 | start = cache->next; | 1484 | start = cache->next; |
| 1478 | 1485 | ||
| @@ -1504,14 +1511,32 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code, | |||
| 1504 | if (!glyph) | 1511 | if (!glyph) |
| 1505 | return NULL; | 1512 | return NULL; |
| 1506 | 1513 | ||
| 1514 | /* Try to instruct the glyph if INTERPRETER is specified. | ||
| 1515 | TODO: support compound glyphs. */ | ||
| 1516 | |||
| 1517 | outline = NULL; | ||
| 1518 | |||
| 1519 | if (interpreter && glyph->simple) | ||
| 1520 | { | ||
| 1521 | error = sfnt_interpret_simple_glyph (glyph, interpreter, | ||
| 1522 | metrics, &value); | ||
| 1523 | |||
| 1524 | if (!error) | ||
| 1525 | { | ||
| 1526 | outline = sfnt_build_instructed_outline (value); | ||
| 1527 | xfree (value); | ||
| 1528 | } | ||
| 1529 | } | ||
| 1530 | |||
| 1507 | dcontext.loca_long = loca_long; | 1531 | dcontext.loca_long = loca_long; |
| 1508 | dcontext.loca_short = loca_short; | 1532 | dcontext.loca_short = loca_short; |
| 1509 | dcontext.glyf = glyf; | 1533 | dcontext.glyf = glyf; |
| 1510 | 1534 | ||
| 1511 | outline = sfnt_build_glyph_outline (glyph, head, pixel_size, | 1535 | if (!outline) |
| 1512 | sfntfont_get_glyph, | 1536 | outline = sfnt_build_glyph_outline (glyph, head, pixel_size, |
| 1513 | sfntfont_free_glyph, | 1537 | sfntfont_get_glyph, |
| 1514 | &dcontext); | 1538 | sfntfont_free_glyph, |
| 1539 | &dcontext); | ||
| 1515 | xfree (glyph); | 1540 | xfree (glyph); |
| 1516 | 1541 | ||
| 1517 | if (!outline) | 1542 | if (!outline) |
| @@ -1709,6 +1734,9 @@ struct sfnt_font_info | |||
| 1709 | struct sfnt_glyf_table *glyf; | 1734 | struct sfnt_glyf_table *glyf; |
| 1710 | struct sfnt_loca_table_short *loca_short; | 1735 | struct sfnt_loca_table_short *loca_short; |
| 1711 | struct sfnt_loca_table_long *loca_long; | 1736 | struct sfnt_loca_table_long *loca_long; |
| 1737 | struct sfnt_prep_table *prep; | ||
| 1738 | struct sfnt_fpgm_table *fpgm; | ||
| 1739 | struct sfnt_cvt_table *cvt; | ||
| 1712 | 1740 | ||
| 1713 | /* The selected character map. */ | 1741 | /* The selected character map. */ |
| 1714 | struct sfnt_cmap_encoding_subtable_data *cmap_data; | 1742 | struct sfnt_cmap_encoding_subtable_data *cmap_data; |
| @@ -1727,6 +1755,13 @@ struct sfnt_font_info | |||
| 1727 | 1755 | ||
| 1728 | /* Number of elements in the raster cache. */ | 1756 | /* Number of elements in the raster cache. */ |
| 1729 | int raster_cache_size; | 1757 | int raster_cache_size; |
| 1758 | |||
| 1759 | /* Interpreter for grid fitting (if enabled). */ | ||
| 1760 | struct sfnt_interpreter *interpreter; | ||
| 1761 | |||
| 1762 | /* Graphics state after the execution of the font and control value | ||
| 1763 | programs. */ | ||
| 1764 | struct sfnt_graphics_state state; | ||
| 1730 | }; | 1765 | }; |
| 1731 | 1766 | ||
| 1732 | /* Look up the glyph corresponding to the character C in FONT. Return | 1767 | /* Look up the glyph corresponding to the character C in FONT. Return |
| @@ -1813,6 +1848,106 @@ sfntfont_probe_widths (struct sfnt_font_info *font_info) | |||
| 1813 | font_info->font.average_width = total_width / num_characters; | 1848 | font_info->font.average_width = total_width / num_characters; |
| 1814 | } | 1849 | } |
| 1815 | 1850 | ||
| 1851 | /* Initialize the instruction interpreter for INFO, whose file and | ||
| 1852 | offset subtable should be respectively FD and SUBTABLE. Load the | ||
| 1853 | font and preprogram for the pixel size in INFO and its | ||
| 1854 | corresponding point size POINT_SIZE. | ||
| 1855 | |||
| 1856 | The font tables in INFO must already have been initialized. | ||
| 1857 | |||
| 1858 | Set INFO->interpreter, INFO->cvt, INFO->prep, INFO->fpgm and | ||
| 1859 | INFO->state upon success, and leave those fields intact | ||
| 1860 | otherwise. */ | ||
| 1861 | |||
| 1862 | static void | ||
| 1863 | sfntfont_setup_interpreter (int fd, struct sfnt_font_info *info, | ||
| 1864 | struct sfnt_offset_subtable *subtable, | ||
| 1865 | int point_size) | ||
| 1866 | { | ||
| 1867 | struct sfnt_cvt_table *cvt; | ||
| 1868 | struct sfnt_fpgm_table *fpgm; | ||
| 1869 | struct sfnt_prep_table *prep; | ||
| 1870 | struct sfnt_interpreter *interpreter; | ||
| 1871 | const char *error; | ||
| 1872 | struct sfnt_graphics_state state; | ||
| 1873 | |||
| 1874 | /* Try to read the control value program, cvt, and font program | ||
| 1875 | tables. */ | ||
| 1876 | |||
| 1877 | cvt = sfnt_read_cvt_table (fd, subtable); | ||
| 1878 | fpgm = sfnt_read_fpgm_table (fd, subtable); | ||
| 1879 | prep = sfnt_read_prep_table (fd, subtable); | ||
| 1880 | |||
| 1881 | /* If both fpgm and prep are NULL, this font likely has no | ||
| 1882 | instructions, so don't bother setting up the interpreter. */ | ||
| 1883 | |||
| 1884 | if (!fpgm && !prep) | ||
| 1885 | goto bail; | ||
| 1886 | |||
| 1887 | /* Now, create the interpreter using the limits in info->maxp and | ||
| 1888 | info->head. CVT can be NULL. */ | ||
| 1889 | interpreter = sfnt_make_interpreter (info->maxp, cvt, info->head, | ||
| 1890 | info->font.pixel_size, | ||
| 1891 | point_size); | ||
| 1892 | |||
| 1893 | /* Bail if the interpreter couldn't be created. */ | ||
| 1894 | if (!interpreter) | ||
| 1895 | goto bail; | ||
| 1896 | |||
| 1897 | if (fpgm) | ||
| 1898 | { | ||
| 1899 | /* Otherwise, evaluate the font and cvt programs. | ||
| 1900 | |||
| 1901 | FIXME: make sure infinite loops inside these programs | ||
| 1902 | cannot lock up Emacs. */ | ||
| 1903 | |||
| 1904 | error = sfnt_interpret_font_program (interpreter, fpgm); | ||
| 1905 | |||
| 1906 | if (error) | ||
| 1907 | { | ||
| 1908 | /* If an error occurs, log it to the *Messages* buffer. */ | ||
| 1909 | message_with_string ("While interpreting font program: %s", | ||
| 1910 | build_string (error), true); | ||
| 1911 | goto bail1; | ||
| 1912 | } | ||
| 1913 | |||
| 1914 | /* Save the graphics state. */ | ||
| 1915 | state = interpreter->state; | ||
| 1916 | } | ||
| 1917 | |||
| 1918 | if (prep) | ||
| 1919 | { | ||
| 1920 | /* This will overwrite state if the instruction control is set | ||
| 1921 | appropriately. */ | ||
| 1922 | error = sfnt_interpret_control_value_program (interpreter, prep, | ||
| 1923 | &state); | ||
| 1924 | |||
| 1925 | if (error) | ||
| 1926 | { | ||
| 1927 | /* If an error occurs, log it to the *Messages* buffer. */ | ||
| 1928 | message_with_string ("While interpreting preprogram: %s", | ||
| 1929 | build_string (error), true); | ||
| 1930 | goto bail1; | ||
| 1931 | } | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | /* The interpreter has been properly set up. */ | ||
| 1935 | info->fpgm = fpgm; | ||
| 1936 | info->prep = prep; | ||
| 1937 | info->cvt = cvt; | ||
| 1938 | info->state = state; | ||
| 1939 | info->interpreter = interpreter; | ||
| 1940 | |||
| 1941 | return; | ||
| 1942 | |||
| 1943 | bail1: | ||
| 1944 | xfree (interpreter); | ||
| 1945 | bail: | ||
| 1946 | xfree (cvt); | ||
| 1947 | xfree (fpgm); | ||
| 1948 | xfree (prep); | ||
| 1949 | } | ||
| 1950 | |||
| 1816 | /* Open the font corresponding to the font-entity FONT_ENTITY. Return | 1951 | /* Open the font corresponding to the font-entity FONT_ENTITY. Return |
| 1817 | nil upon failure, else the opened font-object. */ | 1952 | nil upon failure, else the opened font-object. */ |
| 1818 | 1953 | ||
| @@ -1829,6 +1964,8 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity, | |||
| 1829 | struct sfnt_cmap_encoding_subtable *subtables; | 1964 | struct sfnt_cmap_encoding_subtable *subtables; |
| 1830 | struct sfnt_cmap_encoding_subtable_data **data; | 1965 | struct sfnt_cmap_encoding_subtable_data **data; |
| 1831 | struct charset *charset; | 1966 | struct charset *charset; |
| 1967 | int point_size; | ||
| 1968 | Display_Info *dpyinfo; | ||
| 1832 | 1969 | ||
| 1833 | if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0) | 1970 | if (XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)) != 0) |
| 1834 | pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)); | 1971 | pixel_size = XFIXNUM (AREF (font_entity, FONT_SIZE_INDEX)); |
| @@ -1868,6 +2005,9 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity, | |||
| 1868 | font_info->loca_short = NULL; | 2005 | font_info->loca_short = NULL; |
| 1869 | font_info->loca_long = NULL; | 2006 | font_info->loca_long = NULL; |
| 1870 | font_info->cmap_data = NULL; | 2007 | font_info->cmap_data = NULL; |
| 2008 | font_info->prep = NULL; | ||
| 2009 | font_info->fpgm = NULL; | ||
| 2010 | font_info->cvt = NULL; | ||
| 1871 | 2011 | ||
| 1872 | font_info->outline_cache.next = &font_info->outline_cache; | 2012 | font_info->outline_cache.next = &font_info->outline_cache; |
| 1873 | font_info->outline_cache.last = &font_info->outline_cache; | 2013 | font_info->outline_cache.last = &font_info->outline_cache; |
| @@ -1875,6 +2015,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity, | |||
| 1875 | font_info->raster_cache.next = &font_info->raster_cache; | 2015 | font_info->raster_cache.next = &font_info->raster_cache; |
| 1876 | font_info->raster_cache.last = &font_info->raster_cache; | 2016 | font_info->raster_cache.last = &font_info->raster_cache; |
| 1877 | font_info->raster_cache_size = 0; | 2017 | font_info->raster_cache_size = 0; |
| 2018 | font_info->interpreter = NULL; | ||
| 1878 | 2019 | ||
| 1879 | /* Open the font. */ | 2020 | /* Open the font. */ |
| 1880 | fd = emacs_open (desc->path, O_RDONLY, 0); | 2021 | fd = emacs_open (desc->path, O_RDONLY, 0); |
| @@ -2027,9 +2168,20 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity, | |||
| 2027 | /* Calculate the xfld name. */ | 2168 | /* Calculate the xfld name. */ |
| 2028 | font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil); | 2169 | font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil); |
| 2029 | 2170 | ||
| 2171 | /* Now try to set up grid fitting for this font. */ | ||
| 2172 | dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 2173 | point_size = PIXEL_TO_POINT (pixel_size, (dpyinfo->resx | ||
| 2174 | * dpyinfo->resy | ||
| 2175 | / 2)); | ||
| 2176 | sfntfont_setup_interpreter (fd, font_info, subtable, | ||
| 2177 | point_size); | ||
| 2178 | |||
| 2030 | /* Close the font file descriptor. */ | 2179 | /* Close the font file descriptor. */ |
| 2031 | emacs_close (fd); | 2180 | emacs_close (fd); |
| 2032 | 2181 | ||
| 2182 | /* Free the offset subtable. */ | ||
| 2183 | xfree (subtable); | ||
| 2184 | |||
| 2033 | /* All done. */ | 2185 | /* All done. */ |
| 2034 | unblock_input (); | 2186 | unblock_input (); |
| 2035 | return font_object; | 2187 | return font_object; |
| @@ -2091,6 +2243,54 @@ sfntfont_encode_char (struct font *font, int c) | |||
| 2091 | } | 2243 | } |
| 2092 | 2244 | ||
| 2093 | /* Measure the single glyph GLYPH in the font FONT and return its | 2245 | /* Measure the single glyph GLYPH in the font FONT and return its |
| 2246 | metrics in *PCM. | ||
| 2247 | |||
| 2248 | Instruct the glyph if possible. | ||
| 2249 | |||
| 2250 | Value is 0 upon success, 1 otherwise. */ | ||
| 2251 | |||
| 2252 | static int | ||
| 2253 | sfntfont_measure_instructed_pcm (struct sfnt_font_info *font, sfnt_glyph glyph, | ||
| 2254 | struct font_metrics *pcm) | ||
| 2255 | { | ||
| 2256 | struct sfnt_glyph_metrics metrics; | ||
| 2257 | struct sfnt_glyph_outline *outline; | ||
| 2258 | |||
| 2259 | /* Ask for unscaled metrics. */ | ||
| 2260 | if (sfnt_lookup_glyph_metrics (glyph, -1, &metrics, font->hmtx, | ||
| 2261 | font->hhea, font->head, font->maxp)) | ||
| 2262 | return 1; | ||
| 2263 | |||
| 2264 | /* Now get the glyph outline, which is required to obtain the rsb, | ||
| 2265 | ascent and descent. */ | ||
| 2266 | outline = sfntfont_get_glyph_outline (glyph, &font->outline_cache, | ||
| 2267 | font->font.pixel_size, | ||
| 2268 | &font->outline_cache_size, | ||
| 2269 | font->glyf, font->head, | ||
| 2270 | font->loca_short, | ||
| 2271 | font->loca_long, | ||
| 2272 | font->interpreter, &metrics); | ||
| 2273 | |||
| 2274 | if (!outline) | ||
| 2275 | return 1; | ||
| 2276 | |||
| 2277 | /* Scale the metrics by the interpreter's scale. */ | ||
| 2278 | sfnt_scale_metrics (&metrics, font->interpreter->scale); | ||
| 2279 | |||
| 2280 | /* How to round lbearing and rbearing? */ | ||
| 2281 | pcm->lbearing = metrics.lbearing >> 16; | ||
| 2282 | pcm->rbearing = outline->xmax >> 16; | ||
| 2283 | |||
| 2284 | /* Round the advance, ascent and descent upwards. */ | ||
| 2285 | pcm->width = SFNT_CEIL_FIXED (metrics.advance) >> 16; | ||
| 2286 | pcm->ascent = SFNT_CEIL_FIXED (outline->ymax) >> 16; | ||
| 2287 | pcm->descent = SFNT_CEIL_FIXED (-outline->ymin) >> 16; | ||
| 2288 | |||
| 2289 | sfntfont_dereference_outline (outline); | ||
| 2290 | return 0; | ||
| 2291 | } | ||
| 2292 | |||
| 2293 | /* Measure the single glyph GLYPH in the font FONT and return its | ||
| 2094 | metrics in *PCM. Value is 0 upon success, 1 otherwise. */ | 2294 | metrics in *PCM. Value is 0 upon success, 1 otherwise. */ |
| 2095 | 2295 | ||
| 2096 | static int | 2296 | static int |
| @@ -2100,6 +2300,10 @@ sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph, | |||
| 2100 | struct sfnt_glyph_metrics metrics; | 2300 | struct sfnt_glyph_metrics metrics; |
| 2101 | struct sfnt_glyph_outline *outline; | 2301 | struct sfnt_glyph_outline *outline; |
| 2102 | 2302 | ||
| 2303 | if (font->interpreter) | ||
| 2304 | /* Use a function which instructs the glyph. */ | ||
| 2305 | return sfntfont_measure_instructed_pcm (font, glyph, pcm); | ||
| 2306 | |||
| 2103 | /* Get the glyph metrics first. */ | 2307 | /* Get the glyph metrics first. */ |
| 2104 | if (sfnt_lookup_glyph_metrics (glyph, font->font.pixel_size, | 2308 | if (sfnt_lookup_glyph_metrics (glyph, font->font.pixel_size, |
| 2105 | &metrics, font->hmtx, font->hhea, | 2309 | &metrics, font->hmtx, font->hhea, |
| @@ -2113,7 +2317,7 @@ sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph, | |||
| 2113 | &font->outline_cache_size, | 2317 | &font->outline_cache_size, |
| 2114 | font->glyf, font->head, | 2318 | font->glyf, font->head, |
| 2115 | font->loca_short, | 2319 | font->loca_short, |
| 2116 | font->loca_long); | 2320 | font->loca_long, NULL, NULL); |
| 2117 | 2321 | ||
| 2118 | if (!outline) | 2322 | if (!outline) |
| 2119 | return 1; | 2323 | return 1; |
| @@ -2192,6 +2396,10 @@ sfntfont_close (struct font *font) | |||
| 2192 | xfree (info->loca_short); | 2396 | xfree (info->loca_short); |
| 2193 | xfree (info->loca_long); | 2397 | xfree (info->loca_long); |
| 2194 | xfree (info->cmap_data); | 2398 | xfree (info->cmap_data); |
| 2399 | xfree (info->prep); | ||
| 2400 | xfree (info->fpgm); | ||
| 2401 | xfree (info->cvt); | ||
| 2402 | xfree (info->interpreter); | ||
| 2195 | 2403 | ||
| 2196 | sfntfont_free_outline_cache (&info->outline_cache); | 2404 | sfntfont_free_outline_cache (&info->outline_cache); |
| 2197 | sfntfont_free_raster_cache (&info->raster_cache); | 2405 | sfntfont_free_raster_cache (&info->raster_cache); |
| @@ -2221,10 +2429,15 @@ sfntfont_draw (struct glyph_string *s, int from, int to, | |||
| 2221 | struct font *font; | 2429 | struct font *font; |
| 2222 | struct sfnt_font_info *info; | 2430 | struct sfnt_font_info *info; |
| 2223 | struct sfnt_glyph_metrics metrics; | 2431 | struct sfnt_glyph_metrics metrics; |
| 2432 | int pixel_size; | ||
| 2224 | 2433 | ||
| 2225 | length = to - from; | 2434 | length = to - from; |
| 2226 | font = s->font; | 2435 | font = s->font; |
| 2227 | info = (struct sfnt_font_info *) font; | 2436 | info = (struct sfnt_font_info *) font; |
| 2437 | pixel_size = font->pixel_size; | ||
| 2438 | |||
| 2439 | if (info->interpreter) | ||
| 2440 | pixel_size = -1; | ||
| 2228 | 2441 | ||
| 2229 | rasters = alloca (length * sizeof *rasters); | 2442 | rasters = alloca (length * sizeof *rasters); |
| 2230 | x_coords = alloca (length * sizeof *x_coords); | 2443 | x_coords = alloca (length * sizeof *x_coords); |
| @@ -2233,8 +2446,9 @@ sfntfont_draw (struct glyph_string *s, int from, int to, | |||
| 2233 | /* Get rasters and outlines for them. */ | 2446 | /* Get rasters and outlines for them. */ |
| 2234 | for (i = from; i < to; ++i) | 2447 | for (i = from; i < to; ++i) |
| 2235 | { | 2448 | { |
| 2236 | /* Look up the metrics for this glyph. */ | 2449 | /* Look up the metrics for this glyph. The metrics are unscaled |
| 2237 | if (sfnt_lookup_glyph_metrics (s->char2b[i], font->pixel_size, | 2450 | if INFO->interpreter is set. */ |
| 2451 | if (sfnt_lookup_glyph_metrics (s->char2b[i], pixel_size, | ||
| 2238 | &metrics, info->hmtx, info->hhea, | 2452 | &metrics, info->hmtx, info->hhea, |
| 2239 | info->head, info->maxp)) | 2453 | info->head, info->maxp)) |
| 2240 | { | 2454 | { |
| @@ -2250,7 +2464,9 @@ sfntfont_draw (struct glyph_string *s, int from, int to, | |||
| 2250 | &info->outline_cache_size, | 2464 | &info->outline_cache_size, |
| 2251 | info->glyf, info->head, | 2465 | info->glyf, info->head, |
| 2252 | info->loca_short, | 2466 | info->loca_short, |
| 2253 | info->loca_long); | 2467 | info->loca_long, |
| 2468 | info->interpreter, | ||
| 2469 | &metrics); | ||
| 2254 | x_coords[i - from] = 0; | 2470 | x_coords[i - from] = 0; |
| 2255 | 2471 | ||
| 2256 | if (!outline) | 2472 | if (!outline) |
| @@ -2259,6 +2475,10 @@ sfntfont_draw (struct glyph_string *s, int from, int to, | |||
| 2259 | continue; | 2475 | continue; |
| 2260 | } | 2476 | } |
| 2261 | 2477 | ||
| 2478 | /* Scale the metrics if info->interpreter is set. */ | ||
| 2479 | if (info->interpreter) | ||
| 2480 | sfnt_scale_metrics (&metrics, info->interpreter->scale); | ||
| 2481 | |||
| 2262 | /* Rasterize the outline. */ | 2482 | /* Rasterize the outline. */ |
| 2263 | rasters[i - from] = sfntfont_get_glyph_raster (s->char2b[i], | 2483 | rasters[i - from] = sfntfont_get_glyph_raster (s->char2b[i], |
| 2264 | &info->raster_cache, | 2484 | &info->raster_cache, |