diff options
| author | Po Lu | 2023-03-26 14:09:15 +0800 |
|---|---|---|
| committer | Po Lu | 2023-03-26 14:09:15 +0800 |
| commit | c0873f2382f575b08b5c9eb6663d7a7acf7ece65 (patch) | |
| tree | 3ad999c79a7aeebeedb008261c5994ca9170e689 /src | |
| parent | d7457e1ce4eed211915a6666cc2e7f61516ed343 (diff) | |
| download | emacs-c0873f2382f575b08b5c9eb6663d7a7acf7ece65.tar.gz emacs-c0873f2382f575b08b5c9eb6663d7a7acf7ece65.zip | |
Update Android port
* src/sfnt.c (sfnt_table_names): Add avar.
(sfnt_read_glyph): Clear distortion fields.
(sfnt_build_glyph_outline): Calculate the outline origin point.
(sfnt_prepare_raster): Apply the origin point to the X axis
offset.
(sfnt_scale_metrics_to_pixel_size): New function.
(sfnt_build_instructed_outline): Use instructed origin phantom
point to determine the outline origin.
(sfnt_compute_phantom_points): Apply origin and advance
distortion.
(struct sfnt_variation_axis, struct sfnt_instance)
(struct sfnt_fvar_table, sfnt_read_fvar_table)
(struct sfnt_gvar_table, sfnt_read_gvar_table)
(sfnt_read_avar_table, struct sfnt_blend, sfnt_init_blend)
(sfnt_free_blend, sfnt_normalize_blend, struct sfnt_tuple_header)
(struct sfnt_gvar_glyph_header, sfnt_read_packed_deltas)
(sfnt_compute_tuple_scale, sfnt_read_cvar_table)
(sfnt_infer_deltas_1, sfnt_vary_simple_glyph, sfnt_infer_deltas)
(sfnt_vary_glyph, sfnt_vary_compound_glyph)
(sfnt_vary_interpreter): New functions. Add structs to
sfntfont.h.
(struct sfnt_test_dcontext, sfnt_test_get_glyph, main): Test
distortable font handling.
* src/sfnt.h (SFNT_ENABLE_HINTING):
(enum sfnt_table):
(struct sfnt_glyph):
(struct sfnt_glyph_outline):
(struct sfnt_raster):
(struct sfnt_default_uvs_table):
(struct sfnt_unicode_value_range):
(struct sfnt_nondefault_uvs_table):
(struct sfnt_uvs_mapping):
(struct sfnt_mapped_variation_selector_record):
(struct sfnt_table_offset_rec):
(struct sfnt_uvs_context):
(struct sfnt_mapped_table):
(struct sfnt_variation_axis):
(struct sfnt_instance):
(struct sfnt_fvar_table):
(struct sfnt_short_frac_correspondence):
(struct sfnt_short_frac_segment):
(struct sfnt_avar_table):
(struct sfnt_tuple_variation):
(struct sfnt_cvar_table):
(struct sfnt_gvar_table):
(struct sfnt_blend):
(struct sfnt_metrics_distortion):
(PROTOTYPE): Update prototypes.
* src/sfntfont.c (sfntfont_get_glyph_outline):
(sfntfont_measure_pcm): Adjust calls.
Diffstat (limited to 'src')
| -rw-r--r-- | src/sfnt.c | 1778 | ||||
| -rw-r--r-- | src/sfnt.h | 583 | ||||
| -rw-r--r-- | src/sfntfont.c | 36 |
3 files changed, 1848 insertions, 549 deletions
diff --git a/src/sfnt.c b/src/sfnt.c index 21b2ea96e1c..8e7a30e3b05 100644 --- a/src/sfnt.c +++ b/src/sfnt.c | |||
| @@ -153,6 +153,7 @@ static uint32_t sfnt_table_names[] = | |||
| 153 | [SFNT_TABLE_FVAR] = 0x66766172, | 153 | [SFNT_TABLE_FVAR] = 0x66766172, |
| 154 | [SFNT_TABLE_GVAR] = 0x67766172, | 154 | [SFNT_TABLE_GVAR] = 0x67766172, |
| 155 | [SFNT_TABLE_CVAR] = 0x63766172, | 155 | [SFNT_TABLE_CVAR] = 0x63766172, |
| 156 | [SFNT_TABLE_AVAR] = 0x61766172, | ||
| 156 | }; | 157 | }; |
| 157 | 158 | ||
| 158 | /* Swap values from TrueType to system byte order. */ | 159 | /* Swap values from TrueType to system byte order. */ |
| @@ -2377,6 +2378,10 @@ sfnt_read_glyph (sfnt_glyph glyph_code, | |||
| 2377 | sfnt_swap16 (&glyph.xmax); | 2378 | sfnt_swap16 (&glyph.xmax); |
| 2378 | sfnt_swap16 (&glyph.ymax); | 2379 | sfnt_swap16 (&glyph.ymax); |
| 2379 | 2380 | ||
| 2381 | /* This is set later on after `sfnt_vary_X_glyph'. */ | ||
| 2382 | glyph.advance_distortion = 0; | ||
| 2383 | glyph.origin_distortion = 0; | ||
| 2384 | |||
| 2380 | /* Figure out what needs to be read based on | 2385 | /* Figure out what needs to be read based on |
| 2381 | glyph.number_of_contours. */ | 2386 | glyph.number_of_contours. */ |
| 2382 | if (glyph.number_of_contours >= 0) | 2387 | if (glyph.number_of_contours >= 0) |
| @@ -3758,6 +3763,9 @@ sfnt_curve_to_and_build (struct sfnt_point control, | |||
| 3758 | given pixel size. Return the outline data with a refcount of 0 | 3763 | given pixel size. Return the outline data with a refcount of 0 |
| 3759 | upon success, or NULL upon failure. | 3764 | upon success, or NULL upon failure. |
| 3760 | 3765 | ||
| 3766 | Use the scaled glyph METRICS to determine the origin point of the | ||
| 3767 | outline. | ||
| 3768 | |||
| 3761 | Call GET_GLYPH and FREE_GLYPH with the specified DCONTEXT to obtain | 3769 | Call GET_GLYPH and FREE_GLYPH with the specified DCONTEXT to obtain |
| 3762 | glyphs for compound glyph subcomponents. | 3770 | glyphs for compound glyph subcomponents. |
| 3763 | 3771 | ||
| @@ -3767,12 +3775,14 @@ TEST_STATIC struct sfnt_glyph_outline * | |||
| 3767 | sfnt_build_glyph_outline (struct sfnt_glyph *glyph, | 3775 | sfnt_build_glyph_outline (struct sfnt_glyph *glyph, |
| 3768 | struct sfnt_head_table *head, | 3776 | struct sfnt_head_table *head, |
| 3769 | int pixel_size, | 3777 | int pixel_size, |
| 3778 | struct sfnt_glyph_metrics *metrics, | ||
| 3770 | sfnt_get_glyph_proc get_glyph, | 3779 | sfnt_get_glyph_proc get_glyph, |
| 3771 | sfnt_free_glyph_proc free_glyph, | 3780 | sfnt_free_glyph_proc free_glyph, |
| 3772 | void *dcontext) | 3781 | void *dcontext) |
| 3773 | { | 3782 | { |
| 3774 | struct sfnt_glyph_outline *outline; | 3783 | struct sfnt_glyph_outline *outline; |
| 3775 | int rc; | 3784 | int rc; |
| 3785 | sfnt_fword origin; | ||
| 3776 | 3786 | ||
| 3777 | memset (&build_outline_context, 0, sizeof build_outline_context); | 3787 | memset (&build_outline_context, 0, sizeof build_outline_context); |
| 3778 | 3788 | ||
| @@ -3825,6 +3835,12 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph, | |||
| 3825 | return NULL; | 3835 | return NULL; |
| 3826 | } | 3836 | } |
| 3827 | 3837 | ||
| 3838 | /* Compute the origin position. */ | ||
| 3839 | origin = outline->xmin - metrics->lbearing; | ||
| 3840 | outline->origin | ||
| 3841 | = (origin + sfnt_mul_fixed (glyph->origin_distortion, | ||
| 3842 | build_outline_context.factor)); | ||
| 3843 | |||
| 3828 | return outline; | 3844 | return outline; |
| 3829 | } | 3845 | } |
| 3830 | 3846 | ||
| @@ -3887,7 +3903,11 @@ sfnt_prepare_raster (struct sfnt_raster *raster, | |||
| 3887 | + (SFNT_POLY_ALIGNMENT - 1)) | 3903 | + (SFNT_POLY_ALIGNMENT - 1)) |
| 3888 | & ~(SFNT_POLY_ALIGNMENT - 1)); | 3904 | & ~(SFNT_POLY_ALIGNMENT - 1)); |
| 3889 | 3905 | ||
| 3890 | raster->offx = sfnt_floor_fixed (outline->xmin) >> 16; | 3906 | /* Apply outline->origin. This is 0 by convention in most fonts. |
| 3907 | However, variable fonts typically change this as variations are | ||
| 3908 | applied. */ | ||
| 3909 | raster->offx = sfnt_floor_fixed (outline->xmin | ||
| 3910 | - outline->origin) >> 16; | ||
| 3891 | raster->offy = sfnt_floor_fixed (outline->ymin) >> 16; | 3911 | raster->offy = sfnt_floor_fixed (outline->ymin) >> 16; |
| 3892 | } | 3912 | } |
| 3893 | 3913 | ||
| @@ -4516,6 +4536,23 @@ sfnt_scale_metrics (struct sfnt_glyph_metrics *metrics, | |||
| 4516 | = sfnt_mul_fixed (metrics->advance * 65536, factor); | 4536 | = sfnt_mul_fixed (metrics->advance * 65536, factor); |
| 4517 | } | 4537 | } |
| 4518 | 4538 | ||
| 4539 | /* Like `sfnt_scale_metrics', except it scales the specified metrics | ||
| 4540 | by a factor calculated using the given PPEM and HEAD table's UPEM | ||
| 4541 | value. */ | ||
| 4542 | |||
| 4543 | MAYBE_UNUSED TEST_STATIC void | ||
| 4544 | sfnt_scale_metrics_to_pixel_size (struct sfnt_glyph_metrics *metrics, | ||
| 4545 | int ppem, | ||
| 4546 | struct sfnt_head_table *head) | ||
| 4547 | { | ||
| 4548 | sfnt_fixed factor; | ||
| 4549 | |||
| 4550 | /* Now calculate the factor scale lbearing and advance up to the | ||
| 4551 | given PPEM size. */ | ||
| 4552 | factor = sfnt_div_fixed (ppem, head->units_per_em); | ||
| 4553 | sfnt_scale_metrics (metrics, factor); | ||
| 4554 | } | ||
| 4555 | |||
| 4519 | 4556 | ||
| 4520 | 4557 | ||
| 4521 | /* Font style parsing. */ | 4558 | /* Font style parsing. */ |
| @@ -4949,8 +4986,6 @@ sfnt_read_ttc_header (int fd) | |||
| 4949 | 4986 | ||
| 4950 | 4987 | ||
| 4951 | 4988 | ||
| 4952 | #ifdef SFNT_ENABLE_HINTING | ||
| 4953 | |||
| 4954 | /* TrueType hinting support. | 4989 | /* TrueType hinting support. |
| 4955 | 4990 | ||
| 4956 | If you do not read the code in this section in conjunction with | 4991 | If you do not read the code in this section in conjunction with |
| @@ -10897,6 +10932,15 @@ sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed) | |||
| 10897 | inside sfnt_decompose_glyph. */ | 10932 | inside sfnt_decompose_glyph. */ |
| 10898 | outline = build_outline_context.outline; | 10933 | outline = build_outline_context.outline; |
| 10899 | 10934 | ||
| 10935 | /* Finally, obtain the origin point of the glyph after it has been | ||
| 10936 | instructed. */ | ||
| 10937 | |||
| 10938 | if (instructed->num_points > 1) | ||
| 10939 | outline->origin | ||
| 10940 | = instructed->x_points[instructed->num_points - 2]; | ||
| 10941 | else | ||
| 10942 | outline->origin = 0; | ||
| 10943 | |||
| 10900 | if (rc) | 10944 | if (rc) |
| 10901 | { | 10945 | { |
| 10902 | xfree (outline); | 10946 | xfree (outline); |
| @@ -10935,6 +10979,10 @@ sfnt_compute_phantom_points (struct sfnt_glyph *glyph, | |||
| 10935 | f1 = glyph->xmin - metrics->lbearing; | 10979 | f1 = glyph->xmin - metrics->lbearing; |
| 10936 | f2 = f1 + metrics->advance; | 10980 | f2 = f1 + metrics->advance; |
| 10937 | 10981 | ||
| 10982 | /* Apply the metrics distortion. */ | ||
| 10983 | f1 += glyph->origin_distortion; | ||
| 10984 | f2 += glyph->advance_distortion; | ||
| 10985 | |||
| 10938 | /* Next, scale both up. */ | 10986 | /* Next, scale both up. */ |
| 10939 | *x1 = sfnt_mul_f26dot6_fixed (f1 * 64, scale); | 10987 | *x1 = sfnt_mul_f26dot6_fixed (f1 * 64, scale); |
| 10940 | *x2 = sfnt_mul_f26dot6_fixed (f2 * 64, scale); | 10988 | *x2 = sfnt_mul_f26dot6_fixed (f2 * 64, scale); |
| @@ -11881,7 +11929,6 @@ sfnt_interpret_compound_glyph (struct sfnt_glyph *glyph, | |||
| 11881 | return NULL; | 11929 | return NULL; |
| 11882 | } | 11930 | } |
| 11883 | 11931 | ||
| 11884 | #endif /* SFNT_ENABLE_HINTING */ | ||
| 11885 | 11932 | ||
| 11886 | 11933 | ||
| 11887 | 11934 | ||
| @@ -12428,8 +12475,6 @@ sfnt_read_table (int fd, struct sfnt_offset_subtable *subtable, | |||
| 12428 | 12475 | ||
| 12429 | #endif /* !TEST */ | 12476 | #endif /* !TEST */ |
| 12430 | 12477 | ||
| 12431 | #ifdef TEST | ||
| 12432 | |||
| 12433 | 12478 | ||
| 12434 | 12479 | ||
| 12435 | /* Glyph variations. Instead of defining separate fonts for each | 12480 | /* Glyph variations. Instead of defining separate fonts for each |
| @@ -12442,83 +12487,12 @@ sfnt_read_table (int fd, struct sfnt_offset_subtable *subtable, | |||
| 12442 | variation), `gvar' (glyph variation) and `cvar' (CVT variation) | 12487 | variation), `gvar' (glyph variation) and `cvar' (CVT variation) |
| 12443 | tables in a font file. */ | 12488 | tables in a font file. */ |
| 12444 | 12489 | ||
| 12445 | struct sfnt_variation_axis | ||
| 12446 | { | ||
| 12447 | /* The axis tag. */ | ||
| 12448 | uint32_t axis_tag; | ||
| 12449 | |||
| 12450 | /* The minimum style coordinate for the axis. */ | ||
| 12451 | sfnt_fixed min_value; | ||
| 12452 | |||
| 12453 | /* The default style coordinate for the axis. */ | ||
| 12454 | sfnt_fixed default_value; | ||
| 12455 | |||
| 12456 | /* The maximum style coordinate for the axis. */ | ||
| 12457 | sfnt_fixed max_value; | ||
| 12458 | |||
| 12459 | /* Set to zero. */ | ||
| 12460 | uint16_t flags; | ||
| 12461 | |||
| 12462 | /* Identifier under which this axis's name will be found in the | ||
| 12463 | `name' table. */ | ||
| 12464 | uint16_t name_id; | ||
| 12465 | }; | ||
| 12466 | |||
| 12467 | struct sfnt_instance | ||
| 12468 | { | ||
| 12469 | /* The instance name ID. */ | ||
| 12470 | uint16_t name_id; | ||
| 12471 | |||
| 12472 | /* Flags. */ | ||
| 12473 | uint16_t flags; | ||
| 12474 | |||
| 12475 | /* Optional PostScript name. */ | ||
| 12476 | uint16_t ps_name_id; | ||
| 12477 | |||
| 12478 | /* Coordinates of each defined instance. */ | ||
| 12479 | sfnt_fixed *coords; | ||
| 12480 | }; | ||
| 12481 | |||
| 12482 | struct sfnt_fvar_table | ||
| 12483 | { | ||
| 12484 | /* Major version; should be 1. */ | ||
| 12485 | uint16_t major_version; | ||
| 12486 | |||
| 12487 | /* Minor version; should be 0. */ | ||
| 12488 | uint16_t minor_version; | ||
| 12489 | |||
| 12490 | /* Offset in bytes from the beginning of the table to the beginning | ||
| 12491 | of the first axis data. */ | ||
| 12492 | uint16_t offset_to_data; | ||
| 12493 | |||
| 12494 | /* Reserved field; always 2. */ | ||
| 12495 | uint16_t count_size_pairs; | ||
| 12496 | |||
| 12497 | /* Number of style axes in this font. */ | ||
| 12498 | uint16_t axis_count; | ||
| 12499 | |||
| 12500 | /* The number of bytes in each variation axis record. Currently 20 | ||
| 12501 | bytes. */ | ||
| 12502 | uint16_t axis_size; | ||
| 12503 | |||
| 12504 | /* The number of named instances for the font found in the | ||
| 12505 | instance array. */ | ||
| 12506 | uint16_t instance_count; | ||
| 12507 | |||
| 12508 | /* The size of each instance record. */ | ||
| 12509 | uint16_t instance_size; | ||
| 12510 | |||
| 12511 | /* Variable length data. */ | ||
| 12512 | struct sfnt_variation_axis *axis; | ||
| 12513 | struct sfnt_instance *instance; | ||
| 12514 | }; | ||
| 12515 | |||
| 12516 | /* Read an fvar table from the given font FD. Use the table directory | 12490 | /* Read an fvar table from the given font FD. Use the table directory |
| 12517 | specified in SUBTABLE. | 12491 | specified in SUBTABLE. |
| 12518 | 12492 | ||
| 12519 | Return the fvar table upon success, else NULL. */ | 12493 | Return the fvar table upon success, else NULL. */ |
| 12520 | 12494 | ||
| 12521 | static struct sfnt_fvar_table * | 12495 | TEST_STATIC struct sfnt_fvar_table * |
| 12522 | sfnt_read_fvar_table (int fd, struct sfnt_offset_subtable *subtable) | 12496 | sfnt_read_fvar_table (int fd, struct sfnt_offset_subtable *subtable) |
| 12523 | { | 12497 | { |
| 12524 | struct sfnt_table_directory *directory; | 12498 | struct sfnt_table_directory *directory; |
| @@ -12745,60 +12719,12 @@ sfnt_read_fvar_table (int fd, struct sfnt_offset_subtable *subtable) | |||
| 12745 | 12719 | ||
| 12746 | 12720 | ||
| 12747 | 12721 | ||
| 12748 | struct sfnt_gvar_table | ||
| 12749 | { | ||
| 12750 | /* Version of the glyph variations table. */ | ||
| 12751 | uint16_t version; | ||
| 12752 | |||
| 12753 | /* Reserved, currently 0. */ | ||
| 12754 | uint16_t reserved; | ||
| 12755 | |||
| 12756 | /* The number of style axes for this font. This must be the same | ||
| 12757 | number as axisCount in the 'fvar' table. */ | ||
| 12758 | uint16_t axis_count; | ||
| 12759 | |||
| 12760 | /* The number of shared coordinates. */ | ||
| 12761 | uint16_t shared_coord_count; | ||
| 12762 | |||
| 12763 | /* Byte offset from the beginning of this table to the list of | ||
| 12764 | shared style coordinates. */ | ||
| 12765 | uint32_t offset_to_coord; | ||
| 12766 | |||
| 12767 | /* The number of glyphs in this font; this should match the number | ||
| 12768 | of the glyphs store elsewhere in the font. */ | ||
| 12769 | uint16_t glyph_count; | ||
| 12770 | |||
| 12771 | /* Bit-field that gives the format of the offset array that | ||
| 12772 | follows. If the flag is 0, the type is uint16. If the flag is 1, | ||
| 12773 | the type is unit 32. */ | ||
| 12774 | uint16_t flags; | ||
| 12775 | |||
| 12776 | /* Byte offset from the beginning of this table to the first glyph | ||
| 12777 | glyphVariationData. */ | ||
| 12778 | uint32_t offset_to_data; | ||
| 12779 | |||
| 12780 | /* Number of bytes in the glyph variation data. */ | ||
| 12781 | size_t data_size; | ||
| 12782 | |||
| 12783 | /* Byte offsets from the beginning of the glyphVariationData array | ||
| 12784 | to the glyphVariationData for each glyph in the font. The format | ||
| 12785 | of this field is set by the flags field. */ | ||
| 12786 | union { | ||
| 12787 | uint16_t *offset_word; | ||
| 12788 | uint32_t *offset_long; | ||
| 12789 | } u; | ||
| 12790 | |||
| 12791 | /* Other variable length data. */ | ||
| 12792 | sfnt_f2dot14 *global_coords; | ||
| 12793 | unsigned char *glyph_variation_data; | ||
| 12794 | }; | ||
| 12795 | |||
| 12796 | /* Read a gvar table from the given font FD. Use the table directory | 12722 | /* Read a gvar table from the given font FD. Use the table directory |
| 12797 | specified in SUBTABLE. | 12723 | specified in SUBTABLE. |
| 12798 | 12724 | ||
| 12799 | Return the gvar table upon success, else NULL. */ | 12725 | Return the gvar table upon success, else NULL. */ |
| 12800 | 12726 | ||
| 12801 | static struct sfnt_gvar_table * | 12727 | TEST_STATIC struct sfnt_gvar_table * |
| 12802 | sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable) | 12728 | sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable) |
| 12803 | { | 12729 | { |
| 12804 | struct sfnt_table_directory *directory; | 12730 | struct sfnt_table_directory *directory; |
| @@ -12956,160 +12882,130 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable) | |||
| 12956 | 12882 | ||
| 12957 | 12883 | ||
| 12958 | 12884 | ||
| 12959 | /* Structure repesenting a set of axis coordinates and their | 12885 | /* Read an avar table from the given font FD. Use the table directory |
| 12960 | normalized equivalents. | 12886 | specified in SUBTABLE. |
| 12961 | 12887 | ||
| 12962 | To use this structure, call | 12888 | Return the avar table upon success, else NULL. */ |
| 12963 | 12889 | ||
| 12964 | sfnt_init_blend (&blend, fvar, gvar) | 12890 | TEST_STATIC struct sfnt_avar_table * |
| 12891 | sfnt_read_avar_table (int fd, struct sfnt_offset_subtable *subtable) | ||
| 12892 | { | ||
| 12893 | struct sfnt_table_directory *directory; | ||
| 12894 | struct sfnt_avar_table *avar; | ||
| 12895 | ssize_t rc; | ||
| 12896 | size_t min_size, size, i, k, j; | ||
| 12897 | uint16_t *buffer; | ||
| 12898 | struct sfnt_short_frac_correspondence *correspondences; | ||
| 12965 | 12899 | ||
| 12966 | on a `struct sfnt_blend *', with an appropriate fvar and gvar | 12900 | /* Find the table in the directory. */ |
| 12967 | table. | ||
| 12968 | 12901 | ||
| 12969 | Then, fill in blend.coords with the un-normalized coordinates, | 12902 | directory = sfnt_find_table (subtable, SFNT_TABLE_AVAR); |
| 12970 | and call | ||
| 12971 | 12903 | ||
| 12972 | sfnt_normalize_blend (&blend) | 12904 | if (!directory) |
| 12905 | return NULL; | ||
| 12973 | 12906 | ||
| 12974 | finally, call sfnt_vary_glyph and related functions. */ | 12907 | min_size = SFNT_ENDOF (struct sfnt_avar_table, axis_count, uint32_t); |
| 12975 | 12908 | ||
| 12976 | struct sfnt_blend | 12909 | /* Check that the length is at least min_size. */ |
| 12977 | { | 12910 | if (directory->length < min_size) |
| 12978 | /* The fvar table. This determines the number of elements in each | 12911 | return NULL; |
| 12979 | of the arrays below. */ | ||
| 12980 | struct sfnt_fvar_table *fvar; | ||
| 12981 | 12912 | ||
| 12982 | /* The gvar table. This provides the glyph variation data. */ | 12913 | /* Seek to the location given in the directory. */ |
| 12983 | struct sfnt_gvar_table *gvar; | 12914 | if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1) |
| 12915 | return NULL; | ||
| 12984 | 12916 | ||
| 12985 | /* Un-normalized coordinates. */ | 12917 | /* Allocate enough to hold the avar table header. */ |
| 12986 | sfnt_fixed *coords; | 12918 | avar = xmalloc (sizeof *avar); |
| 12987 | 12919 | ||
| 12988 | /* Normalized coordinates. */ | 12920 | /* Read the avar table header. */ |
| 12989 | sfnt_fixed *norm_coords; | 12921 | rc = read (fd, avar, min_size); |
| 12990 | }; | 12922 | if (rc != min_size) |
| 12923 | goto bail; | ||
| 12991 | 12924 | ||
| 12992 | /* Initialize the specified BLEND with the given FVAR and GVAR | 12925 | /* Swap what was read. */ |
| 12993 | tables. */ | 12926 | sfnt_swap32 (&avar->version); |
| 12927 | sfnt_swap32 (&avar->axis_count); | ||
| 12994 | 12928 | ||
| 12995 | static void | 12929 | if (avar->version != 0x00010000) |
| 12996 | sfnt_init_blend (struct sfnt_blend *blend, struct sfnt_fvar_table *fvar, | 12930 | goto bail; |
| 12997 | struct sfnt_gvar_table *gvar) | ||
| 12998 | { | ||
| 12999 | size_t size; | ||
| 13000 | 12931 | ||
| 13001 | blend->fvar = fvar; | 12932 | if (avar->axis_count < 0) |
| 13002 | blend->gvar = gvar; | 12933 | goto bail; |
| 13003 | 12934 | ||
| 13004 | /* Allocate a single array to hold both coords and norm_coords. */ | 12935 | /* Allocate a buffer that holds the rest of the data. */ |
| 13005 | size = (fvar->axis_count * sizeof *blend->coords * 2); | 12936 | size = directory->length - min_size; |
| 13006 | blend->coords = xmalloc (size); | 12937 | buffer = xmalloc (size); |
| 13007 | blend->norm_coords = blend->coords + fvar->axis_count; | 12938 | rc = read (fd, buffer, size); |
| 13008 | } | 12939 | if (rc != size) |
| 12940 | goto bail1; | ||
| 13009 | 12941 | ||
| 13010 | /* Free what was initialized in the specified BLEND. */ | 12942 | /* Swap each word. */ |
| 12943 | for (i = 0; i < size / sizeof *buffer; ++i) | ||
| 12944 | sfnt_swap16 (&buffer[i]); | ||
| 13011 | 12945 | ||
| 13012 | static void | 12946 | /* Now, determine how big the resulting data needs to be. Each |
| 13013 | sfnt_free_blend (struct sfnt_blend *blend) | 12947 | struct has a pointer field, and that should be its alignment. */ |
| 13014 | { | ||
| 13015 | xfree (blend->coords); | ||
| 13016 | } | ||
| 13017 | 12948 | ||
| 13018 | /* Normalize BLEND->fvar->axis_count coordinates in BLEND->coords and | 12949 | k = 0; |
| 13019 | place the result in BLEND->norm_coords. */ | 12950 | min_size = sizeof *avar; |
| 12951 | for (i = 0; i < avar->axis_count; ++i) | ||
| 12952 | { | ||
| 12953 | /* Check that k remains within bounds. */ | ||
| 12954 | if (k >= size / sizeof *buffer) | ||
| 12955 | goto bail1; | ||
| 13020 | 12956 | ||
| 13021 | static void | 12957 | /* Now add one struct sfnt_short_frac_segment for each axis and |
| 13022 | sfnt_normalize_blend (struct sfnt_blend *blend) | 12958 | each of its correspondences. */ |
| 13023 | { | 12959 | if (INT_ADD_WRAPV (sizeof (struct sfnt_short_frac_segment), |
| 13024 | struct sfnt_variation_axis *axis; | 12960 | min_size, &min_size) |
| 13025 | int i; | 12961 | || INT_ADD_WRAPV (sizeof (struct sfnt_short_frac_correspondence) |
| 13026 | sfnt_fixed coord; | 12962 | * buffer[k], min_size, &min_size)) |
| 12963 | goto bail1; | ||
| 13027 | 12964 | ||
| 13028 | /* For each axis... */ | 12965 | /* Verify that words from here to buffer[1 + buffer[k] * 2], the |
| 13029 | for (i = 0; i < blend->fvar->axis_count; ++i) | 12966 | next pairCount field, are within bounds. */ |
| 13030 | { | 12967 | if (k + 1 + buffer[k] * 2 > size / sizeof *buffer) |
| 13031 | /* Normalize based on [min, default, max], into [-1, 0, 1]. */ | 12968 | goto bail1; |
| 13032 | axis = &blend->fvar->axis[i]; | ||
| 13033 | 12969 | ||
| 13034 | /* Load the current design coordinate. */ | 12970 | /* Move to the next pairCount field. */ |
| 13035 | coord = blend->coords[i]; | 12971 | k += 1 + buffer[k] * 2; |
| 12972 | } | ||
| 13036 | 12973 | ||
| 13037 | /* Keep it within bounds. */ | 12974 | /* Resize avar to min_size and start filling in various |
| 12975 | pointers. */ | ||
| 12976 | avar = xrealloc (avar, min_size); | ||
| 12977 | avar->segments = (struct sfnt_short_frac_segment *) (avar + 1); | ||
| 12978 | correspondences | ||
| 12979 | = ((struct sfnt_short_frac_correspondence *) (avar->segments | ||
| 12980 | + avar->axis_count)); | ||
| 13038 | 12981 | ||
| 13039 | if (coord > axis->max_value) | 12982 | k = 0; |
| 13040 | coord = axis->max_value; | 12983 | for (i = 0; i < avar->axis_count; ++i) |
| 13041 | else if (coord < axis->min_value) | 12984 | { |
| 13042 | coord = axis->min_value; | 12985 | avar->segments[i].pair_count = buffer[k++]; |
| 12986 | avar->segments[i].correspondence = correspondences; | ||
| 13043 | 12987 | ||
| 13044 | if (coord > axis->default_value) | 12988 | for (j = 0; j < avar->segments[i].pair_count; ++j) |
| 13045 | { | ||
| 13046 | /* Avoid division by 0. */ | ||
| 13047 | if (axis->max_value != axis->default_value) | ||
| 13048 | blend->norm_coords[i] | ||
| 13049 | = sfnt_div_fixed (sfnt_sub (coord, axis->default_value), | ||
| 13050 | sfnt_sub (axis->max_value, | ||
| 13051 | axis->default_value)); | ||
| 13052 | else | ||
| 13053 | blend->norm_coords[i] = 0; | ||
| 13054 | } | ||
| 13055 | else if (coord < axis->default_value) | ||
| 13056 | { | 12989 | { |
| 13057 | if (axis->default_value != axis->min_value) | 12990 | correspondences->from_coord = buffer[k++]; |
| 13058 | blend->norm_coords[i] | 12991 | correspondences->to_coord = buffer[k++]; |
| 13059 | = sfnt_div_fixed (sfnt_sub (coord, axis->default_value), | 12992 | correspondences++; |
| 13060 | sfnt_sub (axis->default_value, | ||
| 13061 | axis->min_value)); | ||
| 13062 | else | ||
| 13063 | blend->norm_coords[i] = 0; | ||
| 13064 | } | 12993 | } |
| 13065 | else | ||
| 13066 | blend->norm_coords[i] = 0; | ||
| 13067 | } | 12994 | } |
| 13068 | 12995 | ||
| 13069 | /* TODO: process avar tables. */ | 12996 | /* Return the read avar table. Free buffer. */ |
| 12997 | xfree (buffer); | ||
| 12998 | return avar; | ||
| 12999 | |||
| 13000 | bail1: | ||
| 13001 | xfree (buffer); | ||
| 13002 | bail: | ||
| 13003 | xfree (avar); | ||
| 13004 | return NULL; | ||
| 13070 | } | 13005 | } |
| 13071 | 13006 | ||
| 13072 | 13007 | ||
| 13073 | 13008 | ||
| 13074 | struct sfnt_tuple_header | ||
| 13075 | { | ||
| 13076 | /* The size in bytes of the serialized data for this tuple variation | ||
| 13077 | table. */ | ||
| 13078 | uint16_t variation_data_size; | ||
| 13079 | |||
| 13080 | /* A packed field. The high 4 bits are flags (see below). The low 12 | ||
| 13081 | bits are an index into a shared tuple records array. */ | ||
| 13082 | uint16_t tuple_index; | ||
| 13083 | |||
| 13084 | /* Embedded coordinate tuples, if any. */ | ||
| 13085 | sfnt_f2dot14 *embedded_coord; | ||
| 13086 | |||
| 13087 | /* Intermediate coordinate tuples, if any. */ | ||
| 13088 | sfnt_f2dot14 *intermediate_coord; | ||
| 13089 | |||
| 13090 | /* Number of points associated with this tuple. | ||
| 13091 | Times two, the number of deltas associated with this tuple. */ | ||
| 13092 | uint16_t npoints; | ||
| 13093 | |||
| 13094 | /* Points associated with this tuple. */ | ||
| 13095 | uint16_t *points; | ||
| 13096 | |||
| 13097 | /* Deltas associated with this tuple. */ | ||
| 13098 | sfnt_fword *deltas; | ||
| 13099 | }; | ||
| 13100 | |||
| 13101 | struct sfnt_gvar_glyph_header | ||
| 13102 | { | ||
| 13103 | /* A packed field. The high 4 bits are flags and the low 12 bits are | ||
| 13104 | the number of tuples for this glyph. The number of tuples can be | ||
| 13105 | any number between 1 and 4095. */ | ||
| 13106 | uint16_t tuple_count; | ||
| 13107 | |||
| 13108 | /* Offset from the start of the GlyphVariationData table to the | ||
| 13109 | serialized data. */ | ||
| 13110 | uint16_t data_offset; | ||
| 13111 | }; | ||
| 13112 | |||
| 13113 | /* Read a sequence of packed points starting from DATA. Return the | 13009 | /* Read a sequence of packed points starting from DATA. Return the |
| 13114 | number of points read in *NPOINTS_RETURN and the array of unpacked | 13010 | number of points read in *NPOINTS_RETURN and the array of unpacked |
| 13115 | points, or NULL upon failure. | 13011 | points, or NULL upon failure. |
| @@ -13234,6 +13130,7 @@ sfnt_read_packed_deltas (unsigned char *restrict data, | |||
| 13234 | sfnt_fword *deltas; | 13130 | sfnt_fword *deltas; |
| 13235 | int i, count; | 13131 | int i, count; |
| 13236 | unsigned char control; | 13132 | unsigned char control; |
| 13133 | uint16_t value; | ||
| 13237 | 13134 | ||
| 13238 | if (data >= end) | 13135 | if (data >= end) |
| 13239 | return NULL; | 13136 | return NULL; |
| @@ -13258,9 +13155,9 @@ sfnt_read_packed_deltas (unsigned char *restrict data, | |||
| 13258 | if (data + 1 >= end) | 13155 | if (data + 1 >= end) |
| 13259 | goto fail; | 13156 | goto fail; |
| 13260 | 13157 | ||
| 13261 | deltas[i] = (signed char) *data++; | 13158 | value = *data++ << 8; |
| 13262 | deltas[i] *= 65536; | 13159 | value |= *data++; |
| 13263 | deltas[i++] |= *data++; | 13160 | deltas[i++] = value; |
| 13264 | } | 13161 | } |
| 13265 | else | 13162 | else |
| 13266 | { | 13163 | { |
| @@ -13282,6 +13179,465 @@ sfnt_read_packed_deltas (unsigned char *restrict data, | |||
| 13282 | return NULL; | 13179 | return NULL; |
| 13283 | } | 13180 | } |
| 13284 | 13181 | ||
| 13182 | /* Read a cvar table from the given font FD. Use the table directory | ||
| 13183 | specified in SUBTABLE, axis information provided in the fvar table | ||
| 13184 | FVAR, and CVT information provided in the cvt table CVT. | ||
| 13185 | |||
| 13186 | Return the cvar table upon success, else NULL. */ | ||
| 13187 | |||
| 13188 | TEST_STATIC struct sfnt_cvar_table * | ||
| 13189 | sfnt_read_cvar_table (int fd, struct sfnt_offset_subtable *subtable, | ||
| 13190 | struct sfnt_fvar_table *fvar, | ||
| 13191 | struct sfnt_cvt_table *cvt) | ||
| 13192 | { | ||
| 13193 | struct sfnt_table_directory *directory; | ||
| 13194 | struct sfnt_cvar_table *cvar; | ||
| 13195 | ssize_t rc; | ||
| 13196 | size_t ntuples, size; | ||
| 13197 | int i, j; | ||
| 13198 | sfnt_f2dot14 *coords; | ||
| 13199 | uint16_t *local, *points, npoints, data_size, min_size, index; | ||
| 13200 | unsigned char *buffer, *data, *end, *tuple; | ||
| 13201 | ptrdiff_t data_offset; | ||
| 13202 | sfnt_fword *deltas; | ||
| 13203 | |||
| 13204 | /* Find the table in the directory. */ | ||
| 13205 | |||
| 13206 | directory = sfnt_find_table (subtable, SFNT_TABLE_CVAR); | ||
| 13207 | |||
| 13208 | if (!directory) | ||
| 13209 | return NULL; | ||
| 13210 | |||
| 13211 | min_size = SFNT_ENDOF (struct sfnt_cvar_table, data_offset, | ||
| 13212 | uint16_t); | ||
| 13213 | |||
| 13214 | /* Check that the length is at least min_size. */ | ||
| 13215 | if (directory->length < min_size) | ||
| 13216 | return NULL; | ||
| 13217 | |||
| 13218 | /* Seek to the location given in the directory. */ | ||
| 13219 | if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1) | ||
| 13220 | return NULL; | ||
| 13221 | |||
| 13222 | /* Allocate enough to hold the cvar table header. */ | ||
| 13223 | cvar = xmalloc (sizeof *cvar); | ||
| 13224 | |||
| 13225 | /* Read the cvar table header. */ | ||
| 13226 | rc = read (fd, cvar, min_size); | ||
| 13227 | if (rc != min_size) | ||
| 13228 | goto bail; | ||
| 13229 | |||
| 13230 | /* Swap what was read. */ | ||
| 13231 | sfnt_swap32 (&cvar->version); | ||
| 13232 | sfnt_swap16 (&cvar->tuple_count); | ||
| 13233 | sfnt_swap16 (&cvar->data_offset); | ||
| 13234 | |||
| 13235 | /* Read the rest of the table. */ | ||
| 13236 | size = directory->length - min_size; | ||
| 13237 | buffer = xmalloc (size); | ||
| 13238 | rc = read (fd, buffer, size); | ||
| 13239 | if (rc != size) | ||
| 13240 | goto bail; | ||
| 13241 | |||
| 13242 | /* Now figure out how large cvar must be by reading the tuples. */ | ||
| 13243 | |||
| 13244 | ntuples = cvar->tuple_count & 0x0fff; | ||
| 13245 | data_offset = ((ptrdiff_t) cvar->data_offset | ||
| 13246 | - (ptrdiff_t) min_size); | ||
| 13247 | end = buffer + size; | ||
| 13248 | |||
| 13249 | if (data_offset < 0) | ||
| 13250 | goto bail1; | ||
| 13251 | |||
| 13252 | /* See if there are shared points, and read them if there are. */ | ||
| 13253 | |||
| 13254 | data = buffer + data_offset; | ||
| 13255 | tuple = buffer; | ||
| 13256 | points = NULL; | ||
| 13257 | |||
| 13258 | if (cvar->tuple_count & 0x8000) | ||
| 13259 | { | ||
| 13260 | points = sfnt_read_packed_points (data, &npoints, end, | ||
| 13261 | &tuple); | ||
| 13262 | if (!points) | ||
| 13263 | goto bail1; | ||
| 13264 | |||
| 13265 | /* Add npoints words to the size. */ | ||
| 13266 | size = npoints * sizeof *points; | ||
| 13267 | } | ||
| 13268 | else | ||
| 13269 | size = 0; | ||
| 13270 | |||
| 13271 | while (ntuples--) | ||
| 13272 | { | ||
| 13273 | data = buffer + data_offset; | ||
| 13274 | |||
| 13275 | /* Read the tuple. */ | ||
| 13276 | if (tuple + 3 >= end) | ||
| 13277 | goto bail2; | ||
| 13278 | |||
| 13279 | memcpy (&data_size, tuple, sizeof data_size); | ||
| 13280 | tuple += sizeof data_size; | ||
| 13281 | memcpy (&index, tuple, sizeof index); | ||
| 13282 | tuple += sizeof index; | ||
| 13283 | sfnt_swap16 (&data_size); | ||
| 13284 | sfnt_swap16 (&index); | ||
| 13285 | |||
| 13286 | /* Increment the offset to the data by the data size specified | ||
| 13287 | here. */ | ||
| 13288 | data_offset += data_size; | ||
| 13289 | |||
| 13290 | if (index & 0x8000) | ||
| 13291 | { | ||
| 13292 | /* Embedded coordinates are present. Read each | ||
| 13293 | coordinate and add it to the size. */ | ||
| 13294 | |||
| 13295 | if (tuple + fvar->axis_count * sizeof *coords - 1 >= end) | ||
| 13296 | goto bail2; | ||
| 13297 | |||
| 13298 | tuple += sizeof *coords * fvar->axis_count; | ||
| 13299 | if (INT_ADD_WRAPV (size, sizeof *coords * fvar->axis_count, | ||
| 13300 | &size)) | ||
| 13301 | goto bail2; | ||
| 13302 | } | ||
| 13303 | else | ||
| 13304 | /* This table is invalid, as cvar tables don't have global | ||
| 13305 | coordinates. */ | ||
| 13306 | goto bail2; | ||
| 13307 | |||
| 13308 | /* Now read indeterminate tuples if required. */ | ||
| 13309 | if (index & 0x4000) | ||
| 13310 | { | ||
| 13311 | tuple += fvar->axis_count * 4; | ||
| 13312 | if (INT_ADD_WRAPV (size, fvar->axis_count * 4, &size)) | ||
| 13313 | goto bail2; | ||
| 13314 | } | ||
| 13315 | |||
| 13316 | /* Add one point and one delta for each CVT element. */ | ||
| 13317 | if (INT_ADD_WRAPV (size, cvt->num_elements * 4, &size)) | ||
| 13318 | goto bail2; | ||
| 13319 | |||
| 13320 | /* Now add the size of the tuple. */ | ||
| 13321 | if (INT_ADD_WRAPV (size, sizeof *cvar->variation, &size)) | ||
| 13322 | goto bail2; | ||
| 13323 | } | ||
| 13324 | |||
| 13325 | if (INT_ADD_WRAPV (sizeof *cvar, size, &size)) | ||
| 13326 | goto bail2; | ||
| 13327 | |||
| 13328 | /* Reallocate cvar. */ | ||
| 13329 | cvar = xrealloc (cvar, size); | ||
| 13330 | ntuples = cvar->tuple_count & 0x0fff; | ||
| 13331 | cvar->variation = (struct sfnt_tuple_variation *) (cvar + 1); | ||
| 13332 | coords = (sfnt_f2dot14 *) (cvar->variation + ntuples); | ||
| 13333 | tuple = buffer; | ||
| 13334 | |||
| 13335 | data_offset = ((ptrdiff_t) cvar->data_offset | ||
| 13336 | - (ptrdiff_t) min_size); | ||
| 13337 | |||
| 13338 | /* Start reading the tuples into cvar. */ | ||
| 13339 | for (i = 0; i < ntuples; ++i) | ||
| 13340 | { | ||
| 13341 | data = buffer + data_offset; | ||
| 13342 | |||
| 13343 | /* Read the tuple. */ | ||
| 13344 | if (tuple + 3 >= end) | ||
| 13345 | goto bail2; | ||
| 13346 | |||
| 13347 | memcpy (&data_size, tuple, sizeof data_size); | ||
| 13348 | tuple += sizeof data_size; | ||
| 13349 | memcpy (&index, tuple, sizeof index); | ||
| 13350 | tuple += sizeof index; | ||
| 13351 | sfnt_swap16 (&data_size); | ||
| 13352 | sfnt_swap16 (&index); | ||
| 13353 | |||
| 13354 | /* Increment the offset to the data by the data size specified | ||
| 13355 | here. */ | ||
| 13356 | data_offset += data_size; | ||
| 13357 | |||
| 13358 | cvar->variation[i].intermediate_start = NULL; | ||
| 13359 | cvar->variation[i].intermediate_end = NULL; | ||
| 13360 | |||
| 13361 | if (index & 0x8000) | ||
| 13362 | { | ||
| 13363 | /* Embedded coordinates are present. Read each | ||
| 13364 | coordinate. */ | ||
| 13365 | cvar->variation[i].coordinates = coords; | ||
| 13366 | |||
| 13367 | for (j = 0; j < fvar->axis_count; ++j) | ||
| 13368 | { | ||
| 13369 | if (tuple + 1 >= end) | ||
| 13370 | goto bail2; | ||
| 13371 | |||
| 13372 | memcpy (coords++, tuple, sizeof *coords); | ||
| 13373 | tuple += sizeof *coords; | ||
| 13374 | sfnt_swap16 (coords); | ||
| 13375 | } | ||
| 13376 | } | ||
| 13377 | else | ||
| 13378 | goto bail2; | ||
| 13379 | |||
| 13380 | /* Now read indeterminate tuples if required. */ | ||
| 13381 | if (index & 0x4000) | ||
| 13382 | { | ||
| 13383 | cvar->variation[i].intermediate_start = coords; | ||
| 13384 | |||
| 13385 | for (j = 0; j < fvar->axis_count; ++j) | ||
| 13386 | { | ||
| 13387 | if (tuple + 1 >= end) | ||
| 13388 | goto bail2; | ||
| 13389 | |||
| 13390 | memcpy (coords++, tuple, sizeof *coords); | ||
| 13391 | tuple += sizeof *coords; | ||
| 13392 | sfnt_swap16 (coords); | ||
| 13393 | } | ||
| 13394 | |||
| 13395 | cvar->variation[i].intermediate_end = coords; | ||
| 13396 | |||
| 13397 | for (j = 0; j < fvar->axis_count; ++j) | ||
| 13398 | { | ||
| 13399 | if (tuple + 1 >= end) | ||
| 13400 | goto bail2; | ||
| 13401 | |||
| 13402 | memcpy (coords++, tuple, sizeof *coords); | ||
| 13403 | tuple += sizeof *coords; | ||
| 13404 | sfnt_swap16 (coords); | ||
| 13405 | } | ||
| 13406 | } | ||
| 13407 | |||
| 13408 | /* Finally, read private ``point'' numbers. If this flag is not | ||
| 13409 | set, use shared point numbers previously read. | ||
| 13410 | |||
| 13411 | Read at most CVT->num_elements points, as that is all the | ||
| 13412 | storage allocated. */ | ||
| 13413 | |||
| 13414 | if (index & 0x2000) | ||
| 13415 | { | ||
| 13416 | local = sfnt_read_packed_points (data, &cvar->variation[i].num_points, | ||
| 13417 | end, &data); | ||
| 13418 | if (!local) | ||
| 13419 | goto bail2; | ||
| 13420 | |||
| 13421 | /* If points apply to all CVT indices, skip this part. */ | ||
| 13422 | |||
| 13423 | if (cvar->variation[i].num_points != UINT16_MAX) | ||
| 13424 | { | ||
| 13425 | if (cvar->variation[i].num_points > cvt->num_elements) | ||
| 13426 | cvar->variation[i].num_points = cvt->num_elements; | ||
| 13427 | |||
| 13428 | cvar->variation[i].points = (uint16_t *) coords; | ||
| 13429 | for (j = 0; j < cvar->variation[i].num_points; ++j) | ||
| 13430 | *coords++ = local[j]; | ||
| 13431 | xfree (local); | ||
| 13432 | } | ||
| 13433 | else | ||
| 13434 | cvar->variation[i].points = NULL; | ||
| 13435 | } | ||
| 13436 | else | ||
| 13437 | { | ||
| 13438 | /* Copy in the shared point numbers instead. */ | ||
| 13439 | cvar->variation[i].num_points = npoints; | ||
| 13440 | |||
| 13441 | if (npoints != UINT16_MAX) | ||
| 13442 | { | ||
| 13443 | if (cvar->variation[i].num_points > cvt->num_elements) | ||
| 13444 | cvar->variation[i].num_points = cvt->num_elements; | ||
| 13445 | |||
| 13446 | cvar->variation[i].points = (uint16_t *) coords; | ||
| 13447 | for (j = 0; j < cvar->variation[i].num_points; ++j) | ||
| 13448 | *coords++ = points[j]; | ||
| 13449 | } | ||
| 13450 | else | ||
| 13451 | cvar->variation[i].points = NULL; | ||
| 13452 | } | ||
| 13453 | |||
| 13454 | /* And read packed deltas. If cvar->variation[i].num_points is | ||
| 13455 | UINT16_MAX, then there is one delta for each CVT entry. | ||
| 13456 | Otherwise, there are that many deltas. */ | ||
| 13457 | |||
| 13458 | if (cvar->variation[i].num_points == UINT16_MAX) | ||
| 13459 | { | ||
| 13460 | deltas = sfnt_read_packed_deltas (data, end, cvt->num_elements, | ||
| 13461 | &data); | ||
| 13462 | |||
| 13463 | if (!deltas) | ||
| 13464 | goto bail2; | ||
| 13465 | |||
| 13466 | cvar->variation[i].deltas = coords; | ||
| 13467 | |||
| 13468 | for (j = 0; j < cvt->num_elements; ++j) | ||
| 13469 | *coords++ = deltas[j]; | ||
| 13470 | xfree (deltas); | ||
| 13471 | } | ||
| 13472 | else | ||
| 13473 | { | ||
| 13474 | deltas = sfnt_read_packed_deltas (data, end, | ||
| 13475 | cvar->variation[i].num_points, | ||
| 13476 | &data); | ||
| 13477 | if (!deltas) | ||
| 13478 | goto bail2; | ||
| 13479 | |||
| 13480 | cvar->variation[i].deltas = coords; | ||
| 13481 | |||
| 13482 | for (j = 0; j < cvar->variation[i].num_points; ++j) | ||
| 13483 | *coords++ = deltas[j]; | ||
| 13484 | xfree (deltas); | ||
| 13485 | } | ||
| 13486 | } | ||
| 13487 | |||
| 13488 | /* Free data and return the read cvar table. */ | ||
| 13489 | if (points != (void *) -1) | ||
| 13490 | xfree (points); | ||
| 13491 | xfree (buffer); | ||
| 13492 | return cvar; | ||
| 13493 | |||
| 13494 | bail2: | ||
| 13495 | if (points != (void *) -1) | ||
| 13496 | xfree (points); | ||
| 13497 | bail1: | ||
| 13498 | xfree (buffer); | ||
| 13499 | bail: | ||
| 13500 | xfree (cvar); | ||
| 13501 | return NULL; | ||
| 13502 | } | ||
| 13503 | |||
| 13504 | |||
| 13505 | |||
| 13506 | /* Initialize the specified BLEND with the given FVAR and GVAR tables. | ||
| 13507 | If non-NULL, adjust normalized coordinates using the axis variation | ||
| 13508 | table AVAR; similarly, adjust interpreter CVT values using CVAR, if | ||
| 13509 | specified. */ | ||
| 13510 | |||
| 13511 | TEST_STATIC void | ||
| 13512 | sfnt_init_blend (struct sfnt_blend *blend, struct sfnt_fvar_table *fvar, | ||
| 13513 | struct sfnt_gvar_table *gvar, struct sfnt_avar_table *avar, | ||
| 13514 | struct sfnt_cvar_table *cvar) | ||
| 13515 | { | ||
| 13516 | size_t size; | ||
| 13517 | |||
| 13518 | blend->fvar = fvar; | ||
| 13519 | blend->gvar = gvar; | ||
| 13520 | blend->avar = avar; | ||
| 13521 | blend->cvar = cvar; | ||
| 13522 | |||
| 13523 | /* Allocate a single array to hold both coords and norm_coords. */ | ||
| 13524 | size = (fvar->axis_count * sizeof *blend->coords * 2); | ||
| 13525 | blend->coords = xmalloc (size); | ||
| 13526 | blend->norm_coords = blend->coords + fvar->axis_count; | ||
| 13527 | } | ||
| 13528 | |||
| 13529 | /* Free what was initialized in the specified BLEND. */ | ||
| 13530 | |||
| 13531 | TEST_STATIC void | ||
| 13532 | sfnt_free_blend (struct sfnt_blend *blend) | ||
| 13533 | { | ||
| 13534 | xfree (blend->coords); | ||
| 13535 | } | ||
| 13536 | |||
| 13537 | /* Normalize BLEND->fvar->axis_count coordinates in BLEND->coords and | ||
| 13538 | place the result in BLEND->norm_coords. */ | ||
| 13539 | |||
| 13540 | TEST_STATIC void | ||
| 13541 | sfnt_normalize_blend (struct sfnt_blend *blend) | ||
| 13542 | { | ||
| 13543 | struct sfnt_variation_axis *axis; | ||
| 13544 | int i, j; | ||
| 13545 | sfnt_fixed from, coord, j0, j1, j2; | ||
| 13546 | sfnt_fixed from_last, coord_last; | ||
| 13547 | struct sfnt_short_frac_segment *segment; | ||
| 13548 | |||
| 13549 | /* For each axis... */ | ||
| 13550 | for (i = 0; i < blend->fvar->axis_count; ++i) | ||
| 13551 | { | ||
| 13552 | /* Normalize based on [min, default, max], into [-1, 0, 1]. */ | ||
| 13553 | axis = &blend->fvar->axis[i]; | ||
| 13554 | |||
| 13555 | /* Load the current design coordinate. */ | ||
| 13556 | coord = blend->coords[i]; | ||
| 13557 | |||
| 13558 | /* Keep it within bounds. */ | ||
| 13559 | |||
| 13560 | if (coord > axis->max_value) | ||
| 13561 | coord = axis->max_value; | ||
| 13562 | else if (coord < axis->min_value) | ||
| 13563 | coord = axis->min_value; | ||
| 13564 | |||
| 13565 | if (coord > axis->default_value) | ||
| 13566 | { | ||
| 13567 | /* Avoid division by 0. */ | ||
| 13568 | if (axis->max_value != axis->default_value) | ||
| 13569 | blend->norm_coords[i] | ||
| 13570 | = sfnt_div_fixed (sfnt_sub (coord, axis->default_value), | ||
| 13571 | sfnt_sub (axis->max_value, | ||
| 13572 | axis->default_value)); | ||
| 13573 | else | ||
| 13574 | blend->norm_coords[i] = 0; | ||
| 13575 | } | ||
| 13576 | else if (coord < axis->default_value) | ||
| 13577 | { | ||
| 13578 | if (axis->default_value != axis->min_value) | ||
| 13579 | blend->norm_coords[i] | ||
| 13580 | = sfnt_div_fixed (sfnt_sub (coord, axis->default_value), | ||
| 13581 | sfnt_sub (axis->default_value, | ||
| 13582 | axis->min_value)); | ||
| 13583 | else | ||
| 13584 | blend->norm_coords[i] = 0; | ||
| 13585 | } | ||
| 13586 | else | ||
| 13587 | blend->norm_coords[i] = 0; | ||
| 13588 | } | ||
| 13589 | |||
| 13590 | /* Now, apply axis variations, but only if the avar table has the | ||
| 13591 | right number of axes. */ | ||
| 13592 | |||
| 13593 | if (blend->fvar->axis_count == blend->avar->axis_count) | ||
| 13594 | { | ||
| 13595 | for (i = 0; i < blend->fvar->axis_count; ++i) | ||
| 13596 | { | ||
| 13597 | segment = &blend->avar->segments[i]; | ||
| 13598 | |||
| 13599 | /* Search for a correspondence record above the normalized | ||
| 13600 | coordinate of this axis. */ | ||
| 13601 | |||
| 13602 | for (j = 1; j < segment->pair_count; ++j) | ||
| 13603 | { | ||
| 13604 | from = segment->correspondence[j].from_coord * 4; | ||
| 13605 | coord = segment->correspondence[j].to_coord * 4; | ||
| 13606 | |||
| 13607 | if (blend->norm_coords[i] < from) | ||
| 13608 | { | ||
| 13609 | from_last | ||
| 13610 | = segment->correspondence[j - 1].from_coord * 4; | ||
| 13611 | coord_last | ||
| 13612 | = segment->correspondence[j - 1].to_coord * 4; | ||
| 13613 | |||
| 13614 | j0 = blend->norm_coords[i] - from_last; | ||
| 13615 | j1 = coord - coord_last; | ||
| 13616 | j2 = from - from_last; | ||
| 13617 | |||
| 13618 | blend->norm_coords[i] | ||
| 13619 | = (sfnt_multiply_divide_signed (j0, j1, j2) + coord_last); | ||
| 13620 | break; | ||
| 13621 | } | ||
| 13622 | } | ||
| 13623 | } | ||
| 13624 | } | ||
| 13625 | } | ||
| 13626 | |||
| 13627 | |||
| 13628 | |||
| 13629 | struct sfnt_gvar_glyph_header | ||
| 13630 | { | ||
| 13631 | /* A packed field. The high 4 bits are flags and the low 12 bits are | ||
| 13632 | the number of tuples for this glyph. The number of tuples can be | ||
| 13633 | any number between 1 and 4095. */ | ||
| 13634 | uint16_t tuple_count; | ||
| 13635 | |||
| 13636 | /* Offset from the start of the GlyphVariationData table to the | ||
| 13637 | serialized data. */ | ||
| 13638 | uint16_t data_offset; | ||
| 13639 | }; | ||
| 13640 | |||
| 13285 | /* Given a BLEND containing normalized coordinates, an array of | 13641 | /* Given a BLEND containing normalized coordinates, an array of |
| 13286 | BLEND->gvar->axis_count tuple coordinates, and, if INTERMEDIATE_P, | 13642 | BLEND->gvar->axis_count tuple coordinates, and, if INTERMEDIATE_P, |
| 13287 | a range of tuple coordinates from INTERMEDIATE_START to | 13643 | a range of tuple coordinates from INTERMEDIATE_START to |
| @@ -13758,13 +14114,15 @@ sfnt_infer_deltas (struct sfnt_glyph *glyph, bool *touched, | |||
| 13758 | - contains two elements for each axis, and its axis has a value | 14114 | - contains two elements for each axis, and its axis has a value |
| 13759 | between the first element and the second. | 14115 | between the first element and the second. |
| 13760 | 14116 | ||
| 13761 | After the deltas are applied, any points without deltas must be | 14117 | Return the deltas that would normally be applied to the two phantom |
| 13762 | interpolated similar to an IUP instruction. In addition, deltas | 14118 | points describing horizontal bounds in *DISTORTION. Do not |
| 13763 | may also be applied to phantom points within a glyph. */ | 14119 | transform the outline to reflect adjustments to the origin |
| 14120 | point. */ | ||
| 13764 | 14121 | ||
| 13765 | static int | 14122 | TEST_STATIC int |
| 13766 | sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | 14123 | sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id, |
| 13767 | struct sfnt_glyph *glyph) | 14124 | struct sfnt_glyph *glyph, |
| 14125 | struct sfnt_metrics_distortion *distortion) | ||
| 13768 | { | 14126 | { |
| 13769 | uint32_t offset; | 14127 | uint32_t offset; |
| 13770 | struct sfnt_gvar_glyph_header header; | 14128 | struct sfnt_gvar_glyph_header header; |
| @@ -13775,7 +14133,7 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 13775 | sfnt_f2dot14 *restrict coords; | 14133 | sfnt_f2dot14 *restrict coords; |
| 13776 | sfnt_f2dot14 *restrict intermediate_start; | 14134 | sfnt_f2dot14 *restrict intermediate_start; |
| 13777 | sfnt_f2dot14 *restrict intermediate_end; | 14135 | sfnt_f2dot14 *restrict intermediate_end; |
| 13778 | sfnt_fword *dx, *dy, fword; | 14136 | sfnt_fword *restrict dx, *restrict dy, fword; |
| 13779 | struct sfnt_gvar_table *gvar; | 14137 | struct sfnt_gvar_table *gvar; |
| 13780 | uint16_t *local_points, n_local_points; | 14138 | uint16_t *local_points, n_local_points; |
| 13781 | sfnt_fixed scale; | 14139 | sfnt_fixed scale; |
| @@ -13806,6 +14164,10 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 13806 | if (offset + sizeof header > gvar->data_size) | 14164 | if (offset + sizeof header > gvar->data_size) |
| 13807 | return 1; | 14165 | return 1; |
| 13808 | 14166 | ||
| 14167 | /* Clear the distortion. */ | ||
| 14168 | distortion->origin = 0; | ||
| 14169 | distortion->advance = 0; | ||
| 14170 | |||
| 13809 | memcpy (&header, gvar->glyph_variation_data + offset, | 14171 | memcpy (&header, gvar->glyph_variation_data + offset, |
| 13810 | sizeof header); | 14172 | sizeof header); |
| 13811 | 14173 | ||
| @@ -13846,7 +14208,11 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 13846 | /* Start reading each tuple. */ | 14208 | /* Start reading each tuple. */ |
| 13847 | tuple = gvar->glyph_variation_data + offset + sizeof header; | 14209 | tuple = gvar->glyph_variation_data + offset + sizeof header; |
| 13848 | 14210 | ||
| 13849 | coords = xmalloc (gvar->axis_count * sizeof *coords * 3); | 14211 | if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) |
| 14212 | coords = xmalloc (gvar->axis_count * sizeof *coords * 3); | ||
| 14213 | else | ||
| 14214 | coords = alloca (gvar->axis_count * sizeof *coords * 3); | ||
| 14215 | |||
| 13850 | intermediate_start = coords + gvar->axis_count; | 14216 | intermediate_start = coords + gvar->axis_count; |
| 13851 | intermediate_end = coords + gvar->axis_count; | 14217 | intermediate_end = coords + gvar->axis_count; |
| 13852 | 14218 | ||
| @@ -13856,7 +14222,7 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 13856 | original_x = NULL; | 14222 | original_x = NULL; |
| 13857 | original_y = NULL; | 14223 | original_y = NULL; |
| 13858 | 14224 | ||
| 13859 | for (i = 0; i < ntuples; ++i) | 14225 | while (ntuples--) |
| 13860 | { | 14226 | { |
| 13861 | data = gvar->glyph_variation_data + offset + data_offset; | 14227 | data = gvar->glyph_variation_data + offset + data_offset; |
| 13862 | 14228 | ||
| @@ -13899,7 +14265,7 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 13899 | gvar->axis_count * sizeof *coords); | 14265 | gvar->axis_count * sizeof *coords); |
| 13900 | 14266 | ||
| 13901 | /* Now read indeterminate tuples if required. */ | 14267 | /* Now read indeterminate tuples if required. */ |
| 13902 | if (index & 0x1000) | 14268 | if (index & 0x4000) |
| 13903 | { | 14269 | { |
| 13904 | for (j = 0; j < gvar->axis_count; ++j) | 14270 | for (j = 0; j < gvar->axis_count; ++j) |
| 13905 | { | 14271 | { |
| @@ -13969,9 +14335,6 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 13969 | /* Deltas are provided for all points in the glyph. | 14335 | /* Deltas are provided for all points in the glyph. |
| 13970 | No glyph should have more than 65535 points. */ | 14336 | No glyph should have more than 65535 points. */ |
| 13971 | 14337 | ||
| 13972 | if (glyph->simple->number_of_points > 65535) | ||
| 13973 | abort (); | ||
| 13974 | |||
| 13975 | /* Add 4 phantom points to each end. */ | 14338 | /* Add 4 phantom points to each end. */ |
| 13976 | dx = sfnt_read_packed_deltas (data, end, | 14339 | dx = sfnt_read_packed_deltas (data, end, |
| 13977 | glyph->simple->number_of_points + 4, | 14340 | glyph->simple->number_of_points + 4, |
| @@ -13993,7 +14356,9 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 13993 | glyph->simple->y_coordinates[i] += fword; | 14356 | glyph->simple->y_coordinates[i] += fword; |
| 13994 | } | 14357 | } |
| 13995 | 14358 | ||
| 13996 | /* TODO: apply metrics variations. */ | 14359 | /* Apply the deltas for the two phantom points. */ |
| 14360 | distortion->origin += sfnt_mul_fixed (dx[i++], scale); | ||
| 14361 | distortion->advance += sfnt_mul_fixed (dx[i], scale); | ||
| 13997 | break; | 14362 | break; |
| 13998 | 14363 | ||
| 13999 | default: | 14364 | default: |
| @@ -14007,10 +14372,22 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 14007 | 14372 | ||
| 14008 | if (!original_x) | 14373 | if (!original_x) |
| 14009 | { | 14374 | { |
| 14010 | touched = xmalloc (sizeof *touched | 14375 | if ((glyph->simple->number_of_points |
| 14011 | * glyph->simple->number_of_points); | 14376 | * sizeof *touched) >= 1024 * 16) |
| 14012 | original_x = xmalloc (sizeof *original_x * 2 | 14377 | touched = xmalloc (sizeof *touched |
| 14013 | * glyph->simple->number_of_points); | 14378 | * glyph->simple->number_of_points); |
| 14379 | else | ||
| 14380 | touched = alloca (sizeof *touched | ||
| 14381 | * glyph->simple->number_of_points); | ||
| 14382 | |||
| 14383 | if ((sizeof *original_x * 2 | ||
| 14384 | * glyph->simple->number_of_points) >= 1024 * 16) | ||
| 14385 | original_x = xmalloc (sizeof *original_x * 2 | ||
| 14386 | * glyph->simple->number_of_points); | ||
| 14387 | else | ||
| 14388 | original_x = alloca (sizeof *original_x * 2 | ||
| 14389 | * glyph->simple->number_of_points); | ||
| 14390 | |||
| 14014 | original_y = original_x + glyph->simple->number_of_points; | 14391 | original_y = original_x + glyph->simple->number_of_points; |
| 14015 | memcpy (original_x, glyph->simple->x_coordinates, | 14392 | memcpy (original_x, glyph->simple->x_coordinates, |
| 14016 | (sizeof *original_x | 14393 | (sizeof *original_x |
| @@ -14025,6 +14402,20 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 14025 | 14402 | ||
| 14026 | for (i = 0; i < point_count; ++i) | 14403 | for (i = 0; i < point_count; ++i) |
| 14027 | { | 14404 | { |
| 14405 | /* Apply deltas to phantom points. */ | ||
| 14406 | |||
| 14407 | if (glyph_points[i] == glyph->simple->number_of_points) | ||
| 14408 | { | ||
| 14409 | distortion->origin += sfnt_mul_fixed (dx[i], scale); | ||
| 14410 | continue; | ||
| 14411 | } | ||
| 14412 | |||
| 14413 | if (glyph_points[i] == glyph->simple->number_of_points + 1) | ||
| 14414 | { | ||
| 14415 | distortion->advance += sfnt_mul_fixed (dx[i], scale); | ||
| 14416 | continue; | ||
| 14417 | } | ||
| 14418 | |||
| 14028 | /* Make sure the point doesn't end up out of bounds. */ | 14419 | /* Make sure the point doesn't end up out of bounds. */ |
| 14029 | if (glyph_points[i] >= glyph->simple->number_of_points) | 14420 | if (glyph_points[i] >= glyph->simple->number_of_points) |
| 14030 | continue; | 14421 | continue; |
| @@ -14038,8 +14429,422 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 14038 | 14429 | ||
| 14039 | sfnt_infer_deltas (glyph, touched, original_x, | 14430 | sfnt_infer_deltas (glyph, touched, original_x, |
| 14040 | original_y); | 14431 | original_y); |
| 14432 | break; | ||
| 14433 | } | ||
| 14434 | |||
| 14435 | xfree (dx); | ||
| 14436 | xfree (dy); | ||
| 14437 | |||
| 14438 | if (local_points != (uint16_t *) -1) | ||
| 14439 | xfree (local_points); | ||
| 14440 | } | ||
| 14441 | |||
| 14442 | /* Return success. */ | ||
| 14443 | |||
| 14444 | if ((glyph->simple->number_of_points | ||
| 14445 | * sizeof *touched) >= 1024 * 16) | ||
| 14446 | xfree (touched); | ||
| 14447 | |||
| 14448 | if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) | ||
| 14449 | xfree (coords); | ||
| 14450 | |||
| 14451 | if ((sizeof *original_x * 2 | ||
| 14452 | * glyph->simple->number_of_points) >= 1024 * 16) | ||
| 14453 | xfree (original_x); | ||
| 14454 | |||
| 14455 | if (points != (uint16_t *) -1) | ||
| 14456 | xfree (points); | ||
| 14457 | |||
| 14458 | /* Set the glyph metrics distortion as well. */ | ||
| 14459 | glyph->advance_distortion = distortion->advance; | ||
| 14460 | glyph->origin_distortion = distortion->origin; | ||
| 14461 | |||
| 14462 | return 0; | ||
| 14463 | |||
| 14464 | fail3: | ||
| 14465 | xfree (dx); | ||
| 14466 | xfree (dy); | ||
| 14467 | xfree (local_points); | ||
| 14468 | fail1: | ||
| 14469 | |||
| 14470 | if ((glyph->simple->number_of_points | ||
| 14471 | * sizeof *touched) >= 1024 * 16) | ||
| 14472 | xfree (touched); | ||
| 14473 | |||
| 14474 | if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) | ||
| 14475 | xfree (coords); | ||
| 14476 | |||
| 14477 | if ((sizeof *original_x * 2 | ||
| 14478 | * glyph->simple->number_of_points) >= 1024 * 16) | ||
| 14479 | xfree (original_x); | ||
| 14480 | |||
| 14481 | if (points != (uint16_t *) -1) | ||
| 14482 | xfree (points); | ||
| 14483 | |||
| 14484 | return 1; | ||
| 14485 | } | ||
| 14486 | |||
| 14487 | /* Read the glyph variation data for the specified glyph ID from | ||
| 14488 | BLEND's gvar table. Apply the deltas specified within to each | ||
| 14489 | component with offsets in the specified compound GLYPH, based on | ||
| 14490 | the specified BLEND. Return distortions to phantom points in | ||
| 14491 | *DISTORTION. | ||
| 14492 | |||
| 14493 | Value is 0 upon success, 1 otherwise. */ | ||
| 14494 | |||
| 14495 | TEST_STATIC int | ||
| 14496 | sfnt_vary_compound_glyph (struct sfnt_blend *blend, sfnt_glyph id, | ||
| 14497 | struct sfnt_glyph *glyph, | ||
| 14498 | struct sfnt_metrics_distortion *distortion) | ||
| 14499 | { | ||
| 14500 | uint32_t offset; | ||
| 14501 | struct sfnt_gvar_glyph_header header; | ||
| 14502 | uint16_t *points, npoints; | ||
| 14503 | int i, ntuples, j, point_count; | ||
| 14504 | unsigned char *tuple, *end, *data; | ||
| 14505 | uint16_t data_size, index, *glyph_points; | ||
| 14506 | sfnt_f2dot14 *restrict coords; | ||
| 14507 | sfnt_f2dot14 *restrict intermediate_start; | ||
| 14508 | sfnt_f2dot14 *restrict intermediate_end; | ||
| 14509 | sfnt_fword *restrict dx, *restrict dy, fword, word; | ||
| 14510 | struct sfnt_gvar_table *gvar; | ||
| 14511 | uint16_t *local_points, n_local_points; | ||
| 14512 | sfnt_fixed scale; | ||
| 14513 | ptrdiff_t data_offset; | ||
| 14514 | bool *touched; | ||
| 14515 | sfnt_fword *restrict original_x, *restrict original_y; | ||
| 14516 | struct sfnt_compound_glyph_component *component; | ||
| 14517 | |||
| 14518 | gvar = blend->gvar; | ||
| 14519 | |||
| 14520 | if (gvar->axis_count != blend->fvar->axis_count) | ||
| 14521 | return 1; | ||
| 14522 | |||
| 14523 | if (gvar->glyph_count <= id) | ||
| 14524 | return 1; | ||
| 14525 | |||
| 14526 | if (gvar->flags & 1) | ||
| 14527 | offset = gvar->u.offset_long[id]; | ||
| 14528 | else | ||
| 14529 | offset = gvar->u.offset_word[id] * 2u; | ||
| 14530 | |||
| 14531 | if (offset >= gvar->data_size) | ||
| 14532 | return 1; | ||
| 14533 | |||
| 14534 | end = gvar->glyph_variation_data + gvar->data_size; | ||
| 14535 | |||
| 14536 | /* Start reading the header. */ | ||
| 14537 | |||
| 14538 | if (offset + sizeof header > gvar->data_size) | ||
| 14539 | return 1; | ||
| 14540 | |||
| 14541 | /* Clear the distortion. */ | ||
| 14542 | distortion->origin = 0; | ||
| 14543 | distortion->advance = 0; | ||
| 14544 | |||
| 14545 | memcpy (&header, gvar->glyph_variation_data + offset, | ||
| 14546 | sizeof header); | ||
| 14547 | |||
| 14548 | /* Swap the header. */ | ||
| 14549 | sfnt_swap16 (&header.tuple_count); | ||
| 14550 | sfnt_swap16 (&header.data_offset); | ||
| 14551 | |||
| 14552 | /* Prepare to read each tuple. */ | ||
| 14553 | ntuples = header.tuple_count & 0x0fff; | ||
| 14554 | |||
| 14555 | /* Initialize the data offset. This is incremented with each tuple | ||
| 14556 | read. */ | ||
| 14557 | data_offset = header.data_offset; | ||
| 14558 | |||
| 14559 | /* If gvar->flags & tuples_share_point_numbers, read the shared | ||
| 14560 | point numbers. */ | ||
| 14561 | |||
| 14562 | npoints = 0; | ||
| 14563 | |||
| 14564 | if (header.tuple_count & 0x8000) | ||
| 14565 | { | ||
| 14566 | data = gvar->glyph_variation_data + offset + data_offset; | ||
| 14567 | points = sfnt_read_packed_points (data, &npoints, end, | ||
| 14568 | &tuple); | ||
| 14569 | |||
| 14570 | if (!points) | ||
| 14571 | return 1; | ||
| 14572 | |||
| 14573 | /* Shared point numbers are part of the data after the tuple | ||
| 14574 | array. Thus, increment data_offset by tuple - data. `tuple' | ||
| 14575 | here holds no relation to a pointer to the current part of | ||
| 14576 | the tuple array that is being read later on. */ | ||
| 14577 | data_offset += tuple - data; | ||
| 14578 | } | ||
| 14579 | else | ||
| 14580 | points = NULL; | ||
| 14581 | |||
| 14582 | /* Start reading each tuple. */ | ||
| 14583 | tuple = gvar->glyph_variation_data + offset + sizeof header; | ||
| 14584 | |||
| 14585 | if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) | ||
| 14586 | coords = xmalloc (gvar->axis_count * sizeof *coords * 3); | ||
| 14587 | else | ||
| 14588 | coords = alloca (gvar->axis_count * sizeof *coords * 3); | ||
| 14589 | |||
| 14590 | intermediate_start = coords + gvar->axis_count; | ||
| 14591 | intermediate_end = coords + gvar->axis_count; | ||
| 14592 | |||
| 14593 | /* Allocate arrays of booleans and fwords to keep track of which | ||
| 14594 | points have been touched. */ | ||
| 14595 | touched = NULL; | ||
| 14596 | original_x = NULL; | ||
| 14597 | original_y = NULL; | ||
| 14598 | |||
| 14599 | while (ntuples--) | ||
| 14600 | { | ||
| 14601 | data = gvar->glyph_variation_data + offset + data_offset; | ||
| 14602 | |||
| 14603 | if (tuple + 3 >= end) | ||
| 14604 | goto fail1; | ||
| 14605 | |||
| 14606 | memcpy (&data_size, tuple, sizeof data_size); | ||
| 14607 | tuple += sizeof data_size; | ||
| 14608 | memcpy (&index, tuple, sizeof index); | ||
| 14609 | tuple += sizeof index; | ||
| 14610 | sfnt_swap16 (&data_size); | ||
| 14611 | sfnt_swap16 (&index); | ||
| 14612 | |||
| 14613 | /* Increment the offset to the data by the data size specified | ||
| 14614 | here. */ | ||
| 14615 | data_offset += data_size; | ||
| 14616 | |||
| 14617 | if (index & 0x8000) | ||
| 14618 | { | ||
| 14619 | /* Embedded coordinates are present. Read each | ||
| 14620 | coordinate and add it to the tuple. */ | ||
| 14621 | for (j = 0; j < gvar->axis_count; ++j) | ||
| 14622 | { | ||
| 14623 | if (tuple + 1 >= end) | ||
| 14624 | goto fail1; | ||
| 14625 | |||
| 14626 | memcpy (&coords[j], tuple, sizeof *coords); | ||
| 14627 | tuple += sizeof *coords; | ||
| 14628 | sfnt_swap16 (&coords[j]); | ||
| 14629 | } | ||
| 14630 | } | ||
| 14631 | else if ((index & 0xfff) > gvar->shared_coord_count) | ||
| 14632 | /* index exceeds the number of shared tuples present. */ | ||
| 14633 | goto fail1; | ||
| 14634 | else | ||
| 14635 | /* index points into gvar->axis_count coordinates making up | ||
| 14636 | the tuple. */ | ||
| 14637 | memcpy (coords, (gvar->global_coords | ||
| 14638 | + ((index & 0xfff) * gvar->axis_count)), | ||
| 14639 | gvar->axis_count * sizeof *coords); | ||
| 14640 | |||
| 14641 | /* Now read indeterminate tuples if required. */ | ||
| 14642 | if (index & 0x4000) | ||
| 14643 | { | ||
| 14644 | for (j = 0; j < gvar->axis_count; ++j) | ||
| 14645 | { | ||
| 14646 | if (tuple + 1 >= end) | ||
| 14647 | goto fail1; | ||
| 14648 | |||
| 14649 | memcpy (&intermediate_start[j], tuple, | ||
| 14650 | sizeof *intermediate_start); | ||
| 14651 | tuple += sizeof *intermediate_start; | ||
| 14652 | sfnt_swap16 (&intermediate_start[j]); | ||
| 14653 | } | ||
| 14654 | |||
| 14655 | for (j = 0; j < gvar->axis_count; ++j) | ||
| 14656 | { | ||
| 14657 | if (tuple + 1 >= end) | ||
| 14658 | goto fail1; | ||
| 14659 | |||
| 14660 | memcpy (&intermediate_end[j], tuple, | ||
| 14661 | sizeof *intermediate_end); | ||
| 14662 | tuple += sizeof *intermediate_end; | ||
| 14663 | sfnt_swap16 (&intermediate_end[j]); | ||
| 14664 | } | ||
| 14665 | } | ||
| 14666 | |||
| 14667 | /* See whether or not the tuple applies to the current variation | ||
| 14668 | configuration, and how much to scale them by. */ | ||
| 14669 | |||
| 14670 | scale = sfnt_compute_tuple_scale (blend, index & 0x1000, | ||
| 14671 | coords, intermediate_start, | ||
| 14672 | intermediate_end); | ||
| 14673 | |||
| 14674 | if (!scale) | ||
| 14675 | continue; | ||
| 14676 | |||
| 14677 | local_points = NULL; | ||
| 14678 | |||
| 14679 | /* Finally, read private point numbers. | ||
| 14680 | Set local_points to those numbers; it will be freed | ||
| 14681 | once the loop ends. */ | ||
| 14682 | |||
| 14683 | if (index & 0x2000) | ||
| 14684 | { | ||
| 14685 | local_points = sfnt_read_packed_points (data, &n_local_points, | ||
| 14686 | end, &data); | ||
| 14687 | if (!local_points) | ||
| 14688 | goto fail1; | ||
| 14689 | |||
| 14690 | point_count = n_local_points; | ||
| 14691 | glyph_points = local_points; | ||
| 14692 | } | ||
| 14693 | else | ||
| 14694 | { | ||
| 14695 | /* If there are no private point numbers, use global | ||
| 14696 | points. */ | ||
| 14697 | point_count = npoints; | ||
| 14698 | glyph_points = points; | ||
| 14699 | } | ||
| 14700 | |||
| 14701 | /* Now, read packed deltas. */ | ||
| 14702 | |||
| 14703 | dx = NULL; | ||
| 14704 | dy = NULL; | ||
| 14705 | |||
| 14706 | switch (point_count) | ||
| 14707 | { | ||
| 14708 | case UINT16_MAX: | ||
| 14709 | /* Deltas are provided for all components in the glyph. */ | ||
| 14710 | |||
| 14711 | /* Add 4 phantom points to each end. */ | ||
| 14712 | dx = sfnt_read_packed_deltas (data, end, | ||
| 14713 | glyph->compound->num_components + 4, | ||
| 14714 | &data); | ||
| 14715 | dy = sfnt_read_packed_deltas (data, end, | ||
| 14716 | glyph->compound->num_components + 4, | ||
| 14717 | &data); | ||
| 14718 | |||
| 14719 | if (!dx || !dy) | ||
| 14720 | goto fail3; | ||
| 14721 | |||
| 14722 | /* Apply each delta to the compound glyph. */ | ||
| 14723 | |||
| 14724 | for (i = 0; i < glyph->compound->num_components; ++i) | ||
| 14725 | { | ||
| 14726 | component = &glyph->compound->components[i]; | ||
| 14727 | |||
| 14728 | /* Check if the component uses deltas at all. */ | ||
| 14729 | if (!(component->flags & 02)) | ||
| 14730 | continue; | ||
| 14731 | |||
| 14732 | /* Vary the X offset. */ | ||
| 14733 | |||
| 14734 | if (!(component->flags & 01)) | ||
| 14735 | word = component->argument1.b; | ||
| 14736 | else | ||
| 14737 | word = component->argument1.d; | ||
| 14738 | |||
| 14739 | fword = sfnt_mul_fixed (dx[i], scale); | ||
| 14740 | component->flags |= 01; | ||
| 14741 | component->argument1.d = word + fword; | ||
| 14742 | |||
| 14743 | /* Vary the Y offset. */ | ||
| 14744 | |||
| 14745 | if (!(component->flags & 01)) | ||
| 14746 | word = component->argument2.b; | ||
| 14747 | else | ||
| 14748 | word = component->argument2.d; | ||
| 14749 | |||
| 14750 | fword = sfnt_mul_fixed (dy[i], scale); | ||
| 14751 | component->flags |= 01; | ||
| 14752 | component->argument2.d = word + fword; | ||
| 14753 | } | ||
| 14754 | |||
| 14755 | /* Apply the deltas for the two phantom points. */ | ||
| 14756 | distortion->origin += sfnt_mul_fixed (dx[i++], scale); | ||
| 14757 | distortion->advance += sfnt_mul_fixed (dx[i], scale); | ||
| 14758 | break; | ||
| 14759 | |||
| 14760 | default: | ||
| 14761 | dx = sfnt_read_packed_deltas (data, end, point_count, &data); | ||
| 14762 | dy = sfnt_read_packed_deltas (data, end, point_count, &data); | ||
| 14763 | |||
| 14764 | if (!dx || !dy) | ||
| 14765 | goto fail3; | ||
| 14766 | |||
| 14767 | /* Deltas are only applied for each point number read. */ | ||
| 14768 | |||
| 14769 | if (!original_x) | ||
| 14770 | { | ||
| 14771 | if ((glyph->compound->num_components | ||
| 14772 | * sizeof *touched) >= 1024 * 16) | ||
| 14773 | touched = xmalloc (sizeof *touched | ||
| 14774 | * glyph->compound->num_components); | ||
| 14775 | else | ||
| 14776 | touched = alloca (sizeof *touched | ||
| 14777 | * glyph->compound->num_components); | ||
| 14778 | |||
| 14779 | if ((sizeof *original_x * 2 | ||
| 14780 | * glyph->compound->num_components) >= 1024 * 16) | ||
| 14781 | original_x = xmalloc (sizeof *original_x * 2 | ||
| 14782 | * glyph->compound->num_components); | ||
| 14783 | else | ||
| 14784 | original_x = alloca (sizeof *original_x * 2 | ||
| 14785 | * glyph->compound->num_components); | ||
| 14786 | |||
| 14787 | original_y = original_x + glyph->compound->num_components; | ||
| 14788 | memcpy (original_x, glyph->simple->x_coordinates, | ||
| 14789 | (sizeof *original_x | ||
| 14790 | * glyph->compound->num_components)); | ||
| 14791 | memcpy (original_y, glyph->simple->y_coordinates, | ||
| 14792 | (sizeof *original_y | ||
| 14793 | * glyph->compound->num_components)); | ||
| 14794 | } | ||
| 14795 | |||
| 14796 | memset (touched, 0, (sizeof *touched | ||
| 14797 | * glyph->compound->num_components)); | ||
| 14798 | |||
| 14799 | for (i = 0; i < point_count; ++i) | ||
| 14800 | { | ||
| 14801 | /* Apply deltas to phantom points. */ | ||
| 14802 | |||
| 14803 | if (glyph_points[i] == glyph->compound->num_components) | ||
| 14804 | { | ||
| 14805 | distortion->origin += sfnt_mul_fixed (dx[i], scale); | ||
| 14806 | continue; | ||
| 14807 | } | ||
| 14808 | |||
| 14809 | if (glyph_points[i] == glyph->compound->num_components + 1) | ||
| 14810 | { | ||
| 14811 | distortion->advance += sfnt_mul_fixed (dx[i], scale); | ||
| 14812 | continue; | ||
| 14813 | } | ||
| 14814 | |||
| 14815 | /* Make sure the point doesn't end up out of bounds. */ | ||
| 14816 | if (glyph_points[i] >= glyph->compound->num_components) | ||
| 14817 | continue; | ||
| 14818 | |||
| 14819 | component = &glyph->compound->components[glyph_points[i]]; | ||
| 14820 | |||
| 14821 | /* Check if the component uses deltas at all. */ | ||
| 14822 | if (!(component->flags & 02)) | ||
| 14823 | continue; | ||
| 14824 | |||
| 14825 | /* Vary the X offset. */ | ||
| 14826 | |||
| 14827 | if (!(component->flags & 01)) | ||
| 14828 | word = component->argument1.b; | ||
| 14829 | else | ||
| 14830 | word = component->argument1.d; | ||
| 14831 | |||
| 14832 | fword = sfnt_mul_fixed (dx[i], scale); | ||
| 14833 | component->flags |= 01; | ||
| 14834 | component->argument1.d = word + fword; | ||
| 14835 | |||
| 14836 | /* Vary the Y offset. */ | ||
| 14837 | |||
| 14838 | if (!(component->flags & 01)) | ||
| 14839 | word = component->argument2.b; | ||
| 14840 | else | ||
| 14841 | word = component->argument2.d; | ||
| 14842 | |||
| 14843 | fword = sfnt_mul_fixed (dy[i], scale); | ||
| 14844 | component->flags |= 01; | ||
| 14845 | component->argument2.d = word + fword; | ||
| 14846 | } | ||
| 14041 | 14847 | ||
| 14042 | /* TODO: apply metrics variations. */ | ||
| 14043 | break; | 14848 | break; |
| 14044 | } | 14849 | } |
| 14045 | 14850 | ||
| @@ -14052,13 +14857,24 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 14052 | 14857 | ||
| 14053 | /* Return success. */ | 14858 | /* Return success. */ |
| 14054 | 14859 | ||
| 14055 | xfree (touched); | 14860 | if ((glyph->compound->num_components |
| 14056 | xfree (coords); | 14861 | * sizeof *touched) >= 1024 * 16) |
| 14057 | xfree (original_x); | 14862 | xfree (touched); |
| 14863 | |||
| 14864 | if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) | ||
| 14865 | xfree (coords); | ||
| 14866 | |||
| 14867 | if ((sizeof *original_x * 2 | ||
| 14868 | * glyph->compound->num_components) >= 1024 * 16) | ||
| 14869 | xfree (original_x); | ||
| 14058 | 14870 | ||
| 14059 | if (points != (uint16_t *) -1) | 14871 | if (points != (uint16_t *) -1) |
| 14060 | xfree (points); | 14872 | xfree (points); |
| 14061 | 14873 | ||
| 14874 | /* Set the glyph metrics distortion as well. */ | ||
| 14875 | glyph->advance_distortion = distortion->advance; | ||
| 14876 | glyph->origin_distortion = distortion->origin; | ||
| 14877 | |||
| 14062 | return 0; | 14878 | return 0; |
| 14063 | 14879 | ||
| 14064 | fail3: | 14880 | fail3: |
| @@ -14066,9 +14882,17 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 14066 | xfree (dy); | 14882 | xfree (dy); |
| 14067 | xfree (local_points); | 14883 | xfree (local_points); |
| 14068 | fail1: | 14884 | fail1: |
| 14069 | xfree (touched); | 14885 | |
| 14070 | xfree (coords); | 14886 | if ((glyph->compound->num_components |
| 14071 | xfree (original_x); | 14887 | * sizeof *touched) >= 1024 * 16) |
| 14888 | xfree (touched); | ||
| 14889 | |||
| 14890 | if (gvar->axis_count * sizeof *coords * 3 >= 1024 * 16) | ||
| 14891 | xfree (coords); | ||
| 14892 | |||
| 14893 | if ((sizeof *original_x * 2 | ||
| 14894 | * glyph->compound->num_components) >= 1024 * 16) | ||
| 14895 | xfree (original_x); | ||
| 14072 | 14896 | ||
| 14073 | if (points != (uint16_t *) -1) | 14897 | if (points != (uint16_t *) -1) |
| 14074 | xfree (points); | 14898 | xfree (points); |
| @@ -14076,7 +14900,66 @@ sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | |||
| 14076 | return 1; | 14900 | return 1; |
| 14077 | } | 14901 | } |
| 14078 | 14902 | ||
| 14079 | #endif /* TEST */ | 14903 | /* Vary the specified INTERPRETER's control value table using the |
| 14904 | variations in BLEND's CVT variations table. | ||
| 14905 | |||
| 14906 | The CVT table used to create INTERPRETER must be the same used | ||
| 14907 | to read BLEND->cvar. If not, behavior is undefined. */ | ||
| 14908 | |||
| 14909 | TEST_STATIC void | ||
| 14910 | sfnt_vary_interpreter (struct sfnt_interpreter *interpreter, | ||
| 14911 | struct sfnt_blend *blend) | ||
| 14912 | { | ||
| 14913 | sfnt_fixed scale; | ||
| 14914 | int i; | ||
| 14915 | struct sfnt_tuple_variation *variation; | ||
| 14916 | size_t ndeltas, j, index; | ||
| 14917 | sfnt_f26dot6 delta; | ||
| 14918 | |||
| 14919 | /* Return if there's no cvar table. */ | ||
| 14920 | if (!blend->cvar) | ||
| 14921 | return; | ||
| 14922 | |||
| 14923 | /* For each tuple in the cvar table... */ | ||
| 14924 | for (i = 0; i < (blend->cvar->tuple_count & 0x0fff); ++i) | ||
| 14925 | { | ||
| 14926 | /* See if the tuple applies. */ | ||
| 14927 | variation = &blend->cvar->variation[i]; | ||
| 14928 | scale = sfnt_compute_tuple_scale (blend, | ||
| 14929 | variation->intermediate_start != NULL, | ||
| 14930 | variation->coordinates, | ||
| 14931 | variation->intermediate_start, | ||
| 14932 | variation->intermediate_end); | ||
| 14933 | if (!scale) | ||
| 14934 | continue; | ||
| 14935 | |||
| 14936 | /* Figure out how many deltas there are. If variation->points, | ||
| 14937 | there are num_points deltas. Otherwise, there are | ||
| 14938 | interpreter->cvt->num_elements deltas. */ | ||
| 14939 | |||
| 14940 | ndeltas = (variation->points | ||
| 14941 | ? variation->num_points | ||
| 14942 | : interpreter->cvt_size); | ||
| 14943 | |||
| 14944 | for (j = 0; j < ndeltas; ++j) | ||
| 14945 | { | ||
| 14946 | /* Figure out which CVT entry this applies to. */ | ||
| 14947 | index = variation->points ? variation->points[j] : j; | ||
| 14948 | |||
| 14949 | if (index > interpreter->cvt_size) | ||
| 14950 | continue; | ||
| 14951 | |||
| 14952 | /* Multiply the delta by the interpreter scale factor and | ||
| 14953 | then the tuple scale factor. */ | ||
| 14954 | delta = sfnt_mul_f26dot6_fixed (variation->deltas[j] * 64, | ||
| 14955 | interpreter->scale); | ||
| 14956 | delta = sfnt_mul_fixed (delta, scale); | ||
| 14957 | |||
| 14958 | /* Apply the delta to the control value table. */ | ||
| 14959 | interpreter->cvt[i] += delta; | ||
| 14960 | } | ||
| 14961 | } | ||
| 14962 | } | ||
| 14080 | 14963 | ||
| 14081 | 14964 | ||
| 14082 | 14965 | ||
| @@ -14088,6 +14971,7 @@ struct sfnt_test_dcontext | |||
| 14088 | struct sfnt_glyf_table *glyf; | 14971 | struct sfnt_glyf_table *glyf; |
| 14089 | struct sfnt_loca_table_short *loca_short; | 14972 | struct sfnt_loca_table_short *loca_short; |
| 14090 | struct sfnt_loca_table_long *loca_long; | 14973 | struct sfnt_loca_table_long *loca_long; |
| 14974 | struct sfnt_blend *blend; | ||
| 14091 | }; | 14975 | }; |
| 14092 | 14976 | ||
| 14093 | /* Global context for test functions. Height of glyph. */ | 14977 | /* Global context for test functions. Height of glyph. */ |
| @@ -14120,17 +15004,31 @@ sfnt_test_curve_to (struct sfnt_point control, | |||
| 14120 | } | 15004 | } |
| 14121 | 15005 | ||
| 14122 | static struct sfnt_glyph * | 15006 | static struct sfnt_glyph * |
| 14123 | sfnt_test_get_glyph (sfnt_glyph glyph, void *dcontext, | 15007 | sfnt_test_get_glyph (sfnt_glyph id, void *dcontext, |
| 14124 | bool *need_free) | 15008 | bool *need_free) |
| 14125 | { | 15009 | { |
| 14126 | struct sfnt_test_dcontext *tables; | 15010 | struct sfnt_test_dcontext *tables; |
| 15011 | struct sfnt_glyph *glyph; | ||
| 15012 | struct sfnt_metrics_distortion distortion; | ||
| 14127 | 15013 | ||
| 14128 | tables = dcontext; | 15014 | tables = dcontext; |
| 14129 | *need_free = true; | 15015 | *need_free = true; |
| 14130 | 15016 | ||
| 14131 | return sfnt_read_glyph (glyph, tables->glyf, | 15017 | glyph = sfnt_read_glyph (id, tables->glyf, |
| 14132 | tables->loca_short, | 15018 | tables->loca_short, |
| 14133 | tables->loca_long); | 15019 | tables->loca_long); |
| 15020 | |||
| 15021 | if (tables->blend && glyph) | ||
| 15022 | { | ||
| 15023 | if (glyph->simple) | ||
| 15024 | sfnt_vary_simple_glyph (tables->blend, id, glyph, | ||
| 15025 | &distortion); | ||
| 15026 | else | ||
| 15027 | sfnt_vary_compound_glyph (tables->blend, id, glyph, | ||
| 15028 | &distortion); | ||
| 15029 | } | ||
| 15030 | |||
| 15031 | return glyph; | ||
| 14134 | } | 15032 | } |
| 14135 | 15033 | ||
| 14136 | static void | 15034 | static void |
| @@ -17881,7 +18779,7 @@ main (int argc, char **argv) | |||
| 17881 | struct sfnt_cmap_encoding_subtable *subtables; | 18779 | struct sfnt_cmap_encoding_subtable *subtables; |
| 17882 | struct sfnt_cmap_encoding_subtable_data **data; | 18780 | struct sfnt_cmap_encoding_subtable_data **data; |
| 17883 | struct sfnt_cmap_table *table; | 18781 | struct sfnt_cmap_table *table; |
| 17884 | int fd, i; | 18782 | int fd, i, j; |
| 17885 | sfnt_char character; | 18783 | sfnt_char character; |
| 17886 | struct sfnt_head_table *head; | 18784 | struct sfnt_head_table *head; |
| 17887 | struct sfnt_hhea_table *hhea; | 18785 | struct sfnt_hhea_table *hhea; |
| @@ -17911,6 +18809,8 @@ main (int argc, char **argv) | |||
| 17911 | struct sfnt_instructed_outline *value; | 18809 | struct sfnt_instructed_outline *value; |
| 17912 | struct sfnt_fvar_table *fvar; | 18810 | struct sfnt_fvar_table *fvar; |
| 17913 | struct sfnt_gvar_table *gvar; | 18811 | struct sfnt_gvar_table *gvar; |
| 18812 | struct sfnt_avar_table *avar; | ||
| 18813 | struct sfnt_cvar_table *cvar; | ||
| 17914 | sfnt_fixed scale; | 18814 | sfnt_fixed scale; |
| 17915 | char *fancy; | 18815 | char *fancy; |
| 17916 | int *advances; | 18816 | int *advances; |
| @@ -17919,6 +18819,7 @@ main (int argc, char **argv) | |||
| 17919 | char *axis_name; | 18819 | char *axis_name; |
| 17920 | struct sfnt_instance *instance; | 18820 | struct sfnt_instance *instance; |
| 17921 | struct sfnt_blend blend; | 18821 | struct sfnt_blend blend; |
| 18822 | struct sfnt_metrics_distortion distortion; | ||
| 17922 | 18823 | ||
| 17923 | if (argc < 2) | 18824 | if (argc < 2) |
| 17924 | return 1; | 18825 | return 1; |
| @@ -18029,8 +18930,8 @@ main (int argc, char **argv) | |||
| 18029 | return 1; | 18930 | return 1; |
| 18030 | } | 18931 | } |
| 18031 | 18932 | ||
| 18032 | #define FANCY_PPEM 12 | 18933 | #define FANCY_PPEM 15 |
| 18033 | #define EASY_PPEM 12 | 18934 | #define EASY_PPEM 15 |
| 18034 | 18935 | ||
| 18035 | interpreter = NULL; | 18936 | interpreter = NULL; |
| 18036 | head = sfnt_read_head_table (fd, font); | 18937 | head = sfnt_read_head_table (fd, font); |
| @@ -18044,16 +18945,123 @@ main (int argc, char **argv) | |||
| 18044 | prep = sfnt_read_prep_table (fd, font); | 18945 | prep = sfnt_read_prep_table (fd, font); |
| 18045 | fvar = sfnt_read_fvar_table (fd, font); | 18946 | fvar = sfnt_read_fvar_table (fd, font); |
| 18046 | gvar = sfnt_read_gvar_table (fd, font); | 18947 | gvar = sfnt_read_gvar_table (fd, font); |
| 18948 | avar = sfnt_read_avar_table (fd, font); | ||
| 18949 | cvar = NULL; | ||
| 18047 | hmtx = NULL; | 18950 | hmtx = NULL; |
| 18048 | 18951 | ||
| 18952 | if (fvar && cvt) | ||
| 18953 | cvar = sfnt_read_cvar_table (fd, font, fvar, cvt); | ||
| 18954 | |||
| 18955 | if (cvar) | ||
| 18956 | fprintf (stderr, "cvar table found\n"); | ||
| 18957 | |||
| 18049 | exec_prep = prep; | 18958 | exec_prep = prep; |
| 18050 | exec_fpgm = fpgm; | 18959 | exec_fpgm = fpgm; |
| 18051 | fancy = getenv ("SFNT_FANCY_TEST"); | 18960 | fancy = getenv ("SFNT_FANCY_TEST"); |
| 18052 | 18961 | ||
| 18962 | loca_long = NULL; | ||
| 18963 | loca_short = NULL; | ||
| 18964 | |||
| 18965 | if (fvar) | ||
| 18966 | { | ||
| 18967 | fprintf (stderr, "FVAR table found!\n" | ||
| 18968 | "version: %"PRIu16".%"PRIu16"\n" | ||
| 18969 | "axis_count: %"PRIu16"\n" | ||
| 18970 | "axis_size: %"PRIu16"\n" | ||
| 18971 | "instance_count: %"PRIu16"\n" | ||
| 18972 | "instance_size: %"PRIu16"\n", | ||
| 18973 | fvar->major_version, | ||
| 18974 | fvar->minor_version, | ||
| 18975 | fvar->axis_count, | ||
| 18976 | fvar->axis_size, | ||
| 18977 | fvar->instance_count, | ||
| 18978 | fvar->instance_size); | ||
| 18979 | |||
| 18980 | for (i = 0; i < fvar->axis_count; ++i) | ||
| 18981 | { | ||
| 18982 | if (name) | ||
| 18983 | { | ||
| 18984 | axis_name | ||
| 18985 | = (char *) sfnt_find_name (name, fvar->axis[i].name_id, | ||
| 18986 | &record); | ||
| 18987 | |||
| 18988 | if (axis_name) | ||
| 18989 | fprintf (stderr, "axis no: %d; name: %.*s\n", | ||
| 18990 | i, record.length, axis_name); | ||
| 18991 | } | ||
| 18992 | |||
| 18993 | fprintf (stderr, " axis: %"PRIx32" %g %g %g\n", | ||
| 18994 | fvar->axis[i].axis_tag, | ||
| 18995 | sfnt_coerce_fixed (fvar->axis[i].min_value), | ||
| 18996 | sfnt_coerce_fixed (fvar->axis[i].default_value), | ||
| 18997 | sfnt_coerce_fixed (fvar->axis[i].max_value)); | ||
| 18998 | } | ||
| 18999 | |||
| 19000 | for (i = 0; i < fvar->instance_count; ++i) | ||
| 19001 | { | ||
| 19002 | if (name) | ||
| 19003 | { | ||
| 19004 | axis_name | ||
| 19005 | = (char *) sfnt_find_name (name, fvar->instance[i].name_id, | ||
| 19006 | &record); | ||
| 19007 | |||
| 19008 | if (axis_name) | ||
| 19009 | fprintf (stderr, "instance no: %d; name: %.*s\n", | ||
| 19010 | i, record.length, axis_name); | ||
| 19011 | } | ||
| 19012 | } | ||
| 19013 | |||
| 19014 | if (fvar->instance_count > 1) | ||
| 19015 | { | ||
| 19016 | printf ("instance? "); | ||
| 19017 | |||
| 19018 | if (scanf ("%d", &i) == EOF) | ||
| 19019 | goto free_lab; | ||
| 19020 | |||
| 19021 | if (i >= fvar->instance_count) | ||
| 19022 | goto free_lab; | ||
| 19023 | |||
| 19024 | if (i >= 0) | ||
| 19025 | instance = &fvar->instance[i]; | ||
| 19026 | } | ||
| 19027 | } | ||
| 19028 | |||
| 19029 | if (gvar) | ||
| 19030 | fprintf (stderr, "gvar table found\n"); | ||
| 19031 | |||
| 19032 | if (avar) | ||
| 19033 | { | ||
| 19034 | fprintf (stderr, "avar table found\n"); | ||
| 19035 | |||
| 19036 | for (i = 0; i < avar->axis_count; ++i) | ||
| 19037 | { | ||
| 19038 | fprintf (stderr, "axis: %d, %"PRIu16" pairs\n", | ||
| 19039 | i, avar->segments[i].pair_count); | ||
| 19040 | |||
| 19041 | for (j = 0; j < avar->segments[i].pair_count; ++j) | ||
| 19042 | fprintf (stderr, "pair: %g, %g\n", | ||
| 19043 | (avar->segments[i].correspondence[j].from_coord | ||
| 19044 | / 16384.0), | ||
| 19045 | (avar->segments[i].correspondence[j].to_coord | ||
| 19046 | / 16384.0)); | ||
| 19047 | } | ||
| 19048 | } | ||
| 19049 | |||
| 19050 | memset (&blend, 0, sizeof blend); | ||
| 19051 | |||
| 19052 | if (instance && gvar) | ||
| 19053 | { | ||
| 19054 | sfnt_init_blend (&blend, fvar, gvar, avar, | ||
| 19055 | cvar); | ||
| 19056 | |||
| 19057 | for (i = 0; i < fvar->axis_count; ++i) | ||
| 19058 | blend.coords[i] = instance->coords[i]; | ||
| 19059 | |||
| 19060 | sfnt_normalize_blend (&blend); | ||
| 19061 | } | ||
| 19062 | |||
| 18053 | if (fancy) | 19063 | if (fancy) |
| 18054 | { | 19064 | { |
| 18055 | loca_long = NULL; | ||
| 18056 | loca_short = NULL; | ||
| 18057 | length = strlen (fancy); | 19065 | length = strlen (fancy); |
| 18058 | scale = sfnt_div_fixed (FANCY_PPEM, head->units_per_em); | 19066 | scale = sfnt_div_fixed (FANCY_PPEM, head->units_per_em); |
| 18059 | 19067 | ||
| @@ -18085,6 +19093,8 @@ main (int argc, char **argv) | |||
| 18085 | 19093 | ||
| 18086 | interpreter = sfnt_make_interpreter (maxp, cvt, head, | 19094 | interpreter = sfnt_make_interpreter (maxp, cvt, head, |
| 18087 | FANCY_PPEM, FANCY_PPEM); | 19095 | FANCY_PPEM, FANCY_PPEM); |
| 19096 | if (instance && gvar) | ||
| 19097 | sfnt_vary_interpreter (interpreter, &blend); | ||
| 18088 | 19098 | ||
| 18089 | if (!interpreter) | 19099 | if (!interpreter) |
| 18090 | exit (1); | 19100 | exit (1); |
| @@ -18128,6 +19138,10 @@ main (int argc, char **argv) | |||
| 18128 | if (!glyph || !glyph->simple) | 19138 | if (!glyph || !glyph->simple) |
| 18129 | exit (3); | 19139 | exit (3); |
| 18130 | 19140 | ||
| 19141 | if (instance && gvar) | ||
| 19142 | sfnt_vary_simple_glyph (&blend, code, glyph, | ||
| 19143 | &distortion); | ||
| 19144 | |||
| 18131 | if (sfnt_lookup_glyph_metrics (code, -1, | 19145 | if (sfnt_lookup_glyph_metrics (code, -1, |
| 18132 | &metrics, | 19146 | &metrics, |
| 18133 | hmtx, hhea, | 19147 | hmtx, hhea, |
| @@ -18159,58 +19173,14 @@ main (int argc, char **argv) | |||
| 18159 | xfree (outline); | 19173 | xfree (outline); |
| 18160 | 19174 | ||
| 18161 | rasters[i] = raster; | 19175 | rasters[i] = raster; |
| 18162 | advances[i] = sfnt_mul_fixed (metrics.advance, scale); | 19176 | advances[i] = (sfnt_mul_fixed (metrics.advance, scale) |
| 19177 | + sfnt_mul_fixed (distortion.advance, scale)); | ||
| 18163 | } | 19178 | } |
| 18164 | 19179 | ||
| 18165 | sfnt_x_raster (rasters, advances, length, hhea, scale); | 19180 | sfnt_x_raster (rasters, advances, length, hhea, scale); |
| 18166 | exit (0); | 19181 | exit (0); |
| 18167 | } | 19182 | } |
| 18168 | 19183 | ||
| 18169 | if (head && maxp && maxp->version >= 0x00010000) | ||
| 18170 | { | ||
| 18171 | fprintf (stderr, "creating interpreter\n" | ||
| 18172 | "the size of the stack is %"PRIu16"\n" | ||
| 18173 | "the size of the twilight zone is %"PRIu16"\n" | ||
| 18174 | "the size of the storage area is %"PRIu16"\n" | ||
| 18175 | "there are at most %"PRIu16" idefs\n" | ||
| 18176 | "there are at most %"PRIu16" fdefs\n" | ||
| 18177 | "the cvt is %zu fwords in length\n", | ||
| 18178 | maxp->max_stack_elements, | ||
| 18179 | maxp->max_twilight_points, | ||
| 18180 | maxp->max_storage, | ||
| 18181 | maxp->max_instruction_defs, | ||
| 18182 | maxp->max_function_defs, | ||
| 18183 | cvt ? cvt->num_elements : 0ul); | ||
| 18184 | |||
| 18185 | interpreter = sfnt_make_interpreter (maxp, cvt, head, | ||
| 18186 | FANCY_PPEM, | ||
| 18187 | FANCY_PPEM); | ||
| 18188 | state = interpreter->state; | ||
| 18189 | |||
| 18190 | if (fpgm) | ||
| 18191 | { | ||
| 18192 | fprintf (stderr, "interpreting the font program, with" | ||
| 18193 | " %zu instructions\n", fpgm->num_instructions); | ||
| 18194 | |||
| 18195 | trap = sfnt_interpret_font_program (interpreter, fpgm); | ||
| 18196 | |||
| 18197 | if (trap) | ||
| 18198 | fprintf (stderr, "**TRAP**: %s\n", trap); | ||
| 18199 | } | ||
| 18200 | |||
| 18201 | if (prep) | ||
| 18202 | { | ||
| 18203 | fprintf (stderr, "interpreting the control value program, with" | ||
| 18204 | " %zu instructions\n", prep->num_instructions); | ||
| 18205 | |||
| 18206 | trap = sfnt_interpret_control_value_program (interpreter, prep, | ||
| 18207 | &state); | ||
| 18208 | |||
| 18209 | if (trap) | ||
| 18210 | fprintf (stderr, "**TRAP**: %s\n", trap); | ||
| 18211 | } | ||
| 18212 | } | ||
| 18213 | |||
| 18214 | if (hhea && maxp) | 19184 | if (hhea && maxp) |
| 18215 | hmtx = sfnt_read_hmtx_table (fd, font, hhea, maxp); | 19185 | hmtx = sfnt_read_hmtx_table (fd, font, hhea, maxp); |
| 18216 | 19186 | ||
| @@ -18315,82 +19285,54 @@ main (int argc, char **argv) | |||
| 18315 | (int) hhea->caret_slope_rise, | 19285 | (int) hhea->caret_slope_rise, |
| 18316 | (int) hhea->caret_slope_run); | 19286 | (int) hhea->caret_slope_run); |
| 18317 | 19287 | ||
| 18318 | if (fvar) | 19288 | if (head && maxp && maxp->version >= 0x00010000) |
| 18319 | { | 19289 | { |
| 18320 | fprintf (stderr, "FVAR table found!\n" | 19290 | fprintf (stderr, "creating interpreter\n" |
| 18321 | "version: %"PRIu16".%"PRIu16"\n" | 19291 | "the size of the stack is %"PRIu16"\n" |
| 18322 | "axis_count: %"PRIu16"\n" | 19292 | "the size of the twilight zone is %"PRIu16"\n" |
| 18323 | "axis_size: %"PRIu16"\n" | 19293 | "the size of the storage area is %"PRIu16"\n" |
| 18324 | "instance_count: %"PRIu16"\n" | 19294 | "there are at most %"PRIu16" idefs\n" |
| 18325 | "instance_size: %"PRIu16"\n", | 19295 | "there are at most %"PRIu16" fdefs\n" |
| 18326 | fvar->major_version, | 19296 | "the cvt is %zu fwords in length\n", |
| 18327 | fvar->minor_version, | 19297 | maxp->max_stack_elements, |
| 18328 | fvar->axis_count, | 19298 | maxp->max_twilight_points, |
| 18329 | fvar->axis_size, | 19299 | maxp->max_storage, |
| 18330 | fvar->instance_count, | 19300 | maxp->max_instruction_defs, |
| 18331 | fvar->instance_size); | 19301 | maxp->max_function_defs, |
| 19302 | cvt ? cvt->num_elements : 0ul); | ||
| 18332 | 19303 | ||
| 18333 | for (i = 0; i < fvar->axis_count; ++i) | 19304 | interpreter = sfnt_make_interpreter (maxp, cvt, head, |
| 18334 | { | 19305 | FANCY_PPEM, |
| 18335 | if (name) | 19306 | FANCY_PPEM); |
| 18336 | { | 19307 | state = interpreter->state; |
| 18337 | axis_name | ||
| 18338 | = (char *) sfnt_find_name (name, fvar->axis[i].name_id, | ||
| 18339 | &record); | ||
| 18340 | 19308 | ||
| 18341 | if (axis_name) | 19309 | if (instance && gvar) |
| 18342 | fprintf (stderr, "axis no: %d; name: %.*s\n", | 19310 | sfnt_vary_interpreter (interpreter, &blend); |
| 18343 | i, record.length, axis_name); | ||
| 18344 | } | ||
| 18345 | 19311 | ||
| 18346 | fprintf (stderr, " axis: %"PRIx32" %g %g %g\n", | 19312 | if (fpgm) |
| 18347 | fvar->axis[i].axis_tag, | ||
| 18348 | sfnt_coerce_fixed (fvar->axis[i].min_value), | ||
| 18349 | sfnt_coerce_fixed (fvar->axis[i].default_value), | ||
| 18350 | sfnt_coerce_fixed (fvar->axis[i].max_value)); | ||
| 18351 | } | ||
| 18352 | |||
| 18353 | for (i = 0; i < fvar->instance_count; ++i) | ||
| 18354 | { | 19313 | { |
| 18355 | if (name) | 19314 | fprintf (stderr, "interpreting the font program, with" |
| 18356 | { | 19315 | " %zu instructions\n", fpgm->num_instructions); |
| 18357 | axis_name | ||
| 18358 | = (char *) sfnt_find_name (name, fvar->instance[i].name_id, | ||
| 18359 | &record); | ||
| 18360 | 19316 | ||
| 18361 | if (axis_name) | 19317 | trap = sfnt_interpret_font_program (interpreter, fpgm); |
| 18362 | fprintf (stderr, "instance no: %d; name: %.*s\n", | 19318 | |
| 18363 | i, record.length, axis_name); | 19319 | if (trap) |
| 18364 | } | 19320 | fprintf (stderr, "**TRAP**: %s\n", trap); |
| 18365 | } | 19321 | } |
| 18366 | 19322 | ||
| 18367 | if (fvar->instance_count > 1) | 19323 | if (prep) |
| 18368 | { | 19324 | { |
| 18369 | printf ("instance? "); | 19325 | fprintf (stderr, "interpreting the control value program, with" |
| 18370 | 19326 | " %zu instructions\n", prep->num_instructions); | |
| 18371 | if (scanf ("%d", &i) == EOF) | ||
| 18372 | goto free_lab; | ||
| 18373 | 19327 | ||
| 18374 | if (i < 0 || i >= fvar->instance_count) | 19328 | trap = sfnt_interpret_control_value_program (interpreter, prep, |
| 18375 | goto free_lab; | 19329 | &state); |
| 18376 | 19330 | ||
| 18377 | instance = &fvar->instance[i]; | 19331 | if (trap) |
| 19332 | fprintf (stderr, "**TRAP**: %s\n", trap); | ||
| 18378 | } | 19333 | } |
| 18379 | } | 19334 | } |
| 18380 | 19335 | ||
| 18381 | if (gvar) | ||
| 18382 | fprintf (stderr, "gvar table found\n"); | ||
| 18383 | |||
| 18384 | if (instance && gvar) | ||
| 18385 | { | ||
| 18386 | sfnt_init_blend (&blend, fvar, gvar); | ||
| 18387 | |||
| 18388 | for (i = 0; i < fvar->axis_count; ++i) | ||
| 18389 | blend.coords[i] = instance->coords[i]; | ||
| 18390 | |||
| 18391 | sfnt_normalize_blend (&blend); | ||
| 18392 | } | ||
| 18393 | |||
| 18394 | while (true) | 19336 | while (true) |
| 18395 | { | 19337 | { |
| 18396 | printf ("table, character? "); | 19338 | printf ("table, character? "); |
| @@ -18428,11 +19370,33 @@ main (int argc, char **argv) | |||
| 18428 | dcontext.loca_short = loca_short; | 19370 | dcontext.loca_short = loca_short; |
| 18429 | dcontext.loca_long = loca_long; | 19371 | dcontext.loca_long = loca_long; |
| 18430 | 19372 | ||
| 19373 | if (instance && gvar) | ||
| 19374 | dcontext.blend = &blend; | ||
| 19375 | else | ||
| 19376 | dcontext.blend = NULL; | ||
| 19377 | |||
| 18431 | if (glyph->simple && instance && gvar) | 19378 | if (glyph->simple && instance && gvar) |
| 18432 | { | 19379 | { |
| 18433 | printf ("applying variations to simple glyph...\n"); | 19380 | printf ("applying variations to simple glyph...\n"); |
| 18434 | 19381 | ||
| 18435 | if (sfnt_vary_glyph (&blend, code, glyph)) | 19382 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); |
| 19383 | if (sfnt_vary_simple_glyph (&blend, code, glyph, | ||
| 19384 | &distortion)) | ||
| 19385 | printf ("variation failed!\n"); | ||
| 19386 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &end); | ||
| 19387 | sub = timespec_sub (end, start); | ||
| 19388 | |||
| 19389 | printf ("time spent varying: %lld sec %ld nsec\n", | ||
| 19390 | (long long) sub.tv_sec, sub.tv_nsec); | ||
| 19391 | printf ("distortions: %"PRIi16", %"PRIi16"\n", | ||
| 19392 | distortion.origin, distortion.advance); | ||
| 19393 | } | ||
| 19394 | else if (instance && gvar) | ||
| 19395 | { | ||
| 19396 | printf ("applying variations to compound glyph...\n"); | ||
| 19397 | |||
| 19398 | if (sfnt_vary_compound_glyph (&blend, code, glyph, | ||
| 19399 | &distortion)) | ||
| 18436 | printf ("variation failed!\n"); | 19400 | printf ("variation failed!\n"); |
| 18437 | } | 19401 | } |
| 18438 | 19402 | ||
| @@ -18444,10 +19408,20 @@ main (int argc, char **argv) | |||
| 18444 | &dcontext)) | 19408 | &dcontext)) |
| 18445 | printf ("decomposition failure\n"); | 19409 | printf ("decomposition failure\n"); |
| 18446 | 19410 | ||
| 19411 | if (sfnt_lookup_glyph_metrics (code, EASY_PPEM, | ||
| 19412 | &metrics, | ||
| 19413 | hmtx, hhea, | ||
| 19414 | head, maxp)) | ||
| 19415 | { | ||
| 19416 | printf ("metrics lookup failure"); | ||
| 19417 | memset (&metrics, 0, sizeof metrics); | ||
| 19418 | } | ||
| 19419 | |||
| 18447 | /* Time this important bit. */ | 19420 | /* Time this important bit. */ |
| 18448 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); | 19421 | clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start); |
| 18449 | outline = sfnt_build_glyph_outline (glyph, head, | 19422 | outline = sfnt_build_glyph_outline (glyph, head, |
| 18450 | EASY_PPEM, | 19423 | EASY_PPEM, |
| 19424 | &metrics, | ||
| 18451 | sfnt_test_get_glyph, | 19425 | sfnt_test_get_glyph, |
| 18452 | sfnt_test_free_glyph, | 19426 | sfnt_test_free_glyph, |
| 18453 | &dcontext); | 19427 | &dcontext); |
| @@ -18618,6 +19592,9 @@ main (int argc, char **argv) | |||
| 18618 | for (i = 0; i < table->num_subtables; ++i) | 19592 | for (i = 0; i < table->num_subtables; ++i) |
| 18619 | xfree (data[i]); | 19593 | xfree (data[i]); |
| 18620 | 19594 | ||
| 19595 | if (instance && gvar) | ||
| 19596 | sfnt_free_blend (&blend); | ||
| 19597 | |||
| 18621 | xfree (table); | 19598 | xfree (table); |
| 18622 | xfree (data); | 19599 | xfree (data); |
| 18623 | xfree (subtables); | 19600 | xfree (subtables); |
| @@ -18637,9 +19614,8 @@ main (int argc, char **argv) | |||
| 18637 | xfree (prep); | 19614 | xfree (prep); |
| 18638 | xfree (fvar); | 19615 | xfree (fvar); |
| 18639 | xfree (gvar); | 19616 | xfree (gvar); |
| 18640 | 19617 | xfree (avar); | |
| 18641 | if (instance && gvar) | 19618 | xfree (cvar); |
| 18642 | sfnt_free_blend (&blend); | ||
| 18643 | 19619 | ||
| 18644 | return 0; | 19620 | return 0; |
| 18645 | } | 19621 | } |
diff --git a/src/sfnt.h b/src/sfnt.h index 82fa343f51d..84e51ff6766 100644 --- a/src/sfnt.h +++ b/src/sfnt.h | |||
| @@ -27,10 +27,6 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| 27 | 27 | ||
| 28 | #include <sys/types.h> | 28 | #include <sys/types.h> |
| 29 | 29 | ||
| 30 | #if defined emacs || defined TEST | ||
| 31 | #define SFNT_ENABLE_HINTING | ||
| 32 | #endif | ||
| 33 | |||
| 34 | 30 | ||
| 35 | 31 | ||
| 36 | /* Container structure and enumerator definitions. */ | 32 | /* Container structure and enumerator definitions. */ |
| @@ -56,6 +52,7 @@ enum sfnt_table | |||
| 56 | SFNT_TABLE_FVAR, | 52 | SFNT_TABLE_FVAR, |
| 57 | SFNT_TABLE_GVAR, | 53 | SFNT_TABLE_GVAR, |
| 58 | SFNT_TABLE_CVAR, | 54 | SFNT_TABLE_CVAR, |
| 55 | SFNT_TABLE_AVAR, | ||
| 59 | }; | 56 | }; |
| 60 | 57 | ||
| 61 | #define SFNT_ENDOF(type, field, type1) \ | 58 | #define SFNT_ENDOF(type, field, type1) \ |
| @@ -664,6 +661,12 @@ struct sfnt_glyph | |||
| 664 | /* Coordinate bounds. */ | 661 | /* Coordinate bounds. */ |
| 665 | sfnt_fword xmin, ymin, xmax, ymax; | 662 | sfnt_fword xmin, ymin, xmax, ymax; |
| 666 | 663 | ||
| 664 | /* Distortion applied to the right side phantom point. */ | ||
| 665 | sfnt_fword advance_distortion; | ||
| 666 | |||
| 667 | /* Distortion applied to the origin point. */ | ||
| 668 | sfnt_fword origin_distortion; | ||
| 669 | |||
| 667 | /* Either a simple glyph or a compound glyph, depending on which is | 670 | /* Either a simple glyph or a compound glyph, depending on which is |
| 668 | set. */ | 671 | set. */ |
| 669 | struct sfnt_simple_glyph *simple; | 672 | struct sfnt_simple_glyph *simple; |
| @@ -718,6 +721,10 @@ struct sfnt_glyph_outline | |||
| 718 | and maximum X and Y positions. */ | 721 | and maximum X and Y positions. */ |
| 719 | sfnt_fixed xmin, ymin, xmax, ymax; | 722 | sfnt_fixed xmin, ymin, xmax, ymax; |
| 720 | 723 | ||
| 724 | /* The origin point of the outline on the X axis. Value defaults to | ||
| 725 | 0. */ | ||
| 726 | sfnt_fixed origin; | ||
| 727 | |||
| 721 | /* Reference count. Initially zero. */ | 728 | /* Reference count. Initially zero. */ |
| 722 | short refcount; | 729 | short refcount; |
| 723 | }; | 730 | }; |
| @@ -739,7 +746,8 @@ struct sfnt_raster | |||
| 739 | /* Basic dimensions of the raster. */ | 746 | /* Basic dimensions of the raster. */ |
| 740 | unsigned short width, height; | 747 | unsigned short width, height; |
| 741 | 748 | ||
| 742 | /* Integer offset to apply to positions in the raster. */ | 749 | /* Integer offset to apply to positions in the raster so that they |
| 750 | start from the origin point of the glyph. */ | ||
| 743 | short offx, offy; | 751 | short offx, offy; |
| 744 | 752 | ||
| 745 | /* The raster stride. */ | 753 | /* The raster stride. */ |
| @@ -966,6 +974,357 @@ enum sfnt_ttc_tag | |||
| 966 | 974 | ||
| 967 | 975 | ||
| 968 | 976 | ||
| 977 | /* Unicode Variation Sequence (UVS) support. */ | ||
| 978 | |||
| 979 | struct sfnt_default_uvs_table | ||
| 980 | { | ||
| 981 | /* Number of ranges that follow. */ | ||
| 982 | uint32_t num_unicode_value_ranges; | ||
| 983 | |||
| 984 | /* Variable length data. */ | ||
| 985 | struct sfnt_unicode_value_range *ranges; | ||
| 986 | }; | ||
| 987 | |||
| 988 | struct sfnt_unicode_value_range | ||
| 989 | { | ||
| 990 | /* First value in this range. */ | ||
| 991 | unsigned int start_unicode_value; | ||
| 992 | |||
| 993 | /* Number of additional values in this range. */ | ||
| 994 | unsigned char additional_count; | ||
| 995 | }; | ||
| 996 | |||
| 997 | struct sfnt_nondefault_uvs_table | ||
| 998 | { | ||
| 999 | /* Number of UVS mappings which follow. */ | ||
| 1000 | uint32_t num_uvs_mappings; | ||
| 1001 | |||
| 1002 | /* Variable length data. */ | ||
| 1003 | struct sfnt_uvs_mapping *mappings; | ||
| 1004 | }; | ||
| 1005 | |||
| 1006 | struct sfnt_uvs_mapping | ||
| 1007 | { | ||
| 1008 | /* Base character value. */ | ||
| 1009 | unsigned int unicode_value; | ||
| 1010 | |||
| 1011 | /* Glyph ID of the base character value. */ | ||
| 1012 | uint16_t base_character_value; | ||
| 1013 | }; | ||
| 1014 | |||
| 1015 | struct sfnt_mapped_variation_selector_record | ||
| 1016 | { | ||
| 1017 | /* The variation selector. */ | ||
| 1018 | unsigned int selector; | ||
| 1019 | |||
| 1020 | /* Its default UVS table. */ | ||
| 1021 | struct sfnt_default_uvs_table *default_uvs; | ||
| 1022 | |||
| 1023 | /* Its nondefault UVS table. */ | ||
| 1024 | struct sfnt_nondefault_uvs_table *nondefault_uvs; | ||
| 1025 | }; | ||
| 1026 | |||
| 1027 | /* Structure describing a single offset to load into a variation | ||
| 1028 | selection context. */ | ||
| 1029 | |||
| 1030 | struct sfnt_table_offset_rec | ||
| 1031 | { | ||
| 1032 | /* The offset from the start of the font file. */ | ||
| 1033 | off_t offset; | ||
| 1034 | |||
| 1035 | /* Whether or not the offset points to a non-default UVS table. */ | ||
| 1036 | bool is_nondefault_table; | ||
| 1037 | |||
| 1038 | /* Pointer to the UVS table. */ | ||
| 1039 | void *table; | ||
| 1040 | }; | ||
| 1041 | |||
| 1042 | struct sfnt_uvs_context | ||
| 1043 | { | ||
| 1044 | /* Number of records and tables. */ | ||
| 1045 | size_t num_records, nmemb; | ||
| 1046 | |||
| 1047 | /* Array of UVS tables. */ | ||
| 1048 | struct sfnt_table_offset_rec *tables; | ||
| 1049 | |||
| 1050 | /* Array of variation selector records mapped to | ||
| 1051 | their corresponding tables. */ | ||
| 1052 | struct sfnt_mapped_variation_selector_record *records; | ||
| 1053 | }; | ||
| 1054 | |||
| 1055 | |||
| 1056 | |||
| 1057 | #if defined HAVE_MMAP && !defined TEST | ||
| 1058 | |||
| 1059 | /* Memory mapping support. */ | ||
| 1060 | |||
| 1061 | struct sfnt_mapped_table | ||
| 1062 | { | ||
| 1063 | /* Pointer to table data. */ | ||
| 1064 | void *data; | ||
| 1065 | |||
| 1066 | /* Pointer to table mapping. */ | ||
| 1067 | void *mapping; | ||
| 1068 | |||
| 1069 | /* Size of mapped data and size of mapping. */ | ||
| 1070 | size_t length, size; | ||
| 1071 | }; | ||
| 1072 | |||
| 1073 | #endif /* HAVE_MMAP && !TEST */ | ||
| 1074 | |||
| 1075 | |||
| 1076 | |||
| 1077 | /* Glyph variation support. */ | ||
| 1078 | |||
| 1079 | /* 2.14 fixed point type used to represent versors of unit | ||
| 1080 | vectors. */ | ||
| 1081 | typedef int16_t sfnt_f2dot14; | ||
| 1082 | |||
| 1083 | /* Forward declaration used only for the distortable font stuff. */ | ||
| 1084 | struct sfnt_cvt_table; | ||
| 1085 | |||
| 1086 | struct sfnt_variation_axis | ||
| 1087 | { | ||
| 1088 | /* The axis tag. */ | ||
| 1089 | uint32_t axis_tag; | ||
| 1090 | |||
| 1091 | /* The minimum style coordinate for the axis. */ | ||
| 1092 | sfnt_fixed min_value; | ||
| 1093 | |||
| 1094 | /* The default style coordinate for the axis. */ | ||
| 1095 | sfnt_fixed default_value; | ||
| 1096 | |||
| 1097 | /* The maximum style coordinate for the axis. */ | ||
| 1098 | sfnt_fixed max_value; | ||
| 1099 | |||
| 1100 | /* Set to zero. */ | ||
| 1101 | uint16_t flags; | ||
| 1102 | |||
| 1103 | /* Identifier under which this axis's name will be found in the | ||
| 1104 | `name' table. */ | ||
| 1105 | uint16_t name_id; | ||
| 1106 | }; | ||
| 1107 | |||
| 1108 | struct sfnt_instance | ||
| 1109 | { | ||
| 1110 | /* The instance name ID. */ | ||
| 1111 | uint16_t name_id; | ||
| 1112 | |||
| 1113 | /* Flags. */ | ||
| 1114 | uint16_t flags; | ||
| 1115 | |||
| 1116 | /* Optional PostScript name. */ | ||
| 1117 | uint16_t ps_name_id; | ||
| 1118 | |||
| 1119 | /* Coordinates of each defined instance. */ | ||
| 1120 | sfnt_fixed *coords; | ||
| 1121 | }; | ||
| 1122 | |||
| 1123 | struct sfnt_fvar_table | ||
| 1124 | { | ||
| 1125 | /* Major version; should be 1. */ | ||
| 1126 | uint16_t major_version; | ||
| 1127 | |||
| 1128 | /* Minor version; should be 0. */ | ||
| 1129 | uint16_t minor_version; | ||
| 1130 | |||
| 1131 | /* Offset in bytes from the beginning of the table to the beginning | ||
| 1132 | of the first axis data. */ | ||
| 1133 | uint16_t offset_to_data; | ||
| 1134 | |||
| 1135 | /* Reserved field; always 2. */ | ||
| 1136 | uint16_t count_size_pairs; | ||
| 1137 | |||
| 1138 | /* Number of style axes in this font. */ | ||
| 1139 | uint16_t axis_count; | ||
| 1140 | |||
| 1141 | /* The number of bytes in each variation axis record. Currently 20 | ||
| 1142 | bytes. */ | ||
| 1143 | uint16_t axis_size; | ||
| 1144 | |||
| 1145 | /* The number of named instances for the font found in the | ||
| 1146 | instance array. */ | ||
| 1147 | uint16_t instance_count; | ||
| 1148 | |||
| 1149 | /* The size of each instance record. */ | ||
| 1150 | uint16_t instance_size; | ||
| 1151 | |||
| 1152 | /* Variable length data. */ | ||
| 1153 | struct sfnt_variation_axis *axis; | ||
| 1154 | struct sfnt_instance *instance; | ||
| 1155 | }; | ||
| 1156 | |||
| 1157 | struct sfnt_short_frac_correspondence | ||
| 1158 | { | ||
| 1159 | /* Value in normalized user space. */ | ||
| 1160 | sfnt_f2dot14 from_coord; | ||
| 1161 | |||
| 1162 | /* Value in normalized axis space. */ | ||
| 1163 | sfnt_f2dot14 to_coord; | ||
| 1164 | }; | ||
| 1165 | |||
| 1166 | struct sfnt_short_frac_segment | ||
| 1167 | { | ||
| 1168 | /* The number of pairs for this axis. */ | ||
| 1169 | uint16_t pair_count; | ||
| 1170 | |||
| 1171 | /* Variable length data. */ | ||
| 1172 | struct sfnt_short_frac_correspondence *correspondence; | ||
| 1173 | }; | ||
| 1174 | |||
| 1175 | struct sfnt_avar_table | ||
| 1176 | { | ||
| 1177 | /* The version of the table. Should be 1.0. */ | ||
| 1178 | sfnt_fixed version; | ||
| 1179 | |||
| 1180 | /* Number of variation axes defined in this table. | ||
| 1181 | XXX: why is this signed? */ | ||
| 1182 | int32_t axis_count; | ||
| 1183 | |||
| 1184 | /* Variable length data. */ | ||
| 1185 | struct sfnt_short_frac_segment *segments; | ||
| 1186 | }; | ||
| 1187 | |||
| 1188 | struct sfnt_tuple_variation | ||
| 1189 | { | ||
| 1190 | /* Tuple point numbers. */ | ||
| 1191 | uint16_t *points; | ||
| 1192 | |||
| 1193 | /* Deltas. */ | ||
| 1194 | sfnt_fword *deltas; | ||
| 1195 | |||
| 1196 | /* Tuple coordinates. One for each axis specified in the [gaf]var | ||
| 1197 | tables. */ | ||
| 1198 | sfnt_f2dot14 *coordinates; | ||
| 1199 | |||
| 1200 | /* Intermediate start and end coordinates. */ | ||
| 1201 | sfnt_f2dot14 *restrict intermediate_start; | ||
| 1202 | |||
| 1203 | /* Intermediate start and end coordinates. */ | ||
| 1204 | sfnt_f2dot14 *restrict intermediate_end; | ||
| 1205 | |||
| 1206 | /* The number of points and deltas present. | ||
| 1207 | |||
| 1208 | UINT16_MAX and POINTS set to NULL means there are deltas for each | ||
| 1209 | CVT entry. */ | ||
| 1210 | uint16_t num_points; | ||
| 1211 | }; | ||
| 1212 | |||
| 1213 | struct sfnt_cvar_table | ||
| 1214 | { | ||
| 1215 | /* The version of this CVT variations table. */ | ||
| 1216 | sfnt_fixed version; | ||
| 1217 | |||
| 1218 | /* Flags. */ | ||
| 1219 | uint16_t tuple_count; | ||
| 1220 | |||
| 1221 | /* Offset from the beginning of the table to the tuple data. */ | ||
| 1222 | uint16_t data_offset; | ||
| 1223 | |||
| 1224 | /* Variable length data. */ | ||
| 1225 | struct sfnt_tuple_variation *variation; | ||
| 1226 | }; | ||
| 1227 | |||
| 1228 | struct sfnt_gvar_table | ||
| 1229 | { | ||
| 1230 | /* Version of the glyph variations table. */ | ||
| 1231 | uint16_t version; | ||
| 1232 | |||
| 1233 | /* Reserved, currently 0. */ | ||
| 1234 | uint16_t reserved; | ||
| 1235 | |||
| 1236 | /* The number of style axes for this font. This must be the same | ||
| 1237 | number as axisCount in the 'fvar' table. */ | ||
| 1238 | uint16_t axis_count; | ||
| 1239 | |||
| 1240 | /* The number of shared coordinates. */ | ||
| 1241 | uint16_t shared_coord_count; | ||
| 1242 | |||
| 1243 | /* Byte offset from the beginning of this table to the list of | ||
| 1244 | shared style coordinates. */ | ||
| 1245 | uint32_t offset_to_coord; | ||
| 1246 | |||
| 1247 | /* The number of glyphs in this font; this should match the number | ||
| 1248 | of the glyphs store elsewhere in the font. */ | ||
| 1249 | uint16_t glyph_count; | ||
| 1250 | |||
| 1251 | /* Bit-field that gives the format of the offset array that | ||
| 1252 | follows. If the flag is 0, the type is uint16. If the flag is 1, | ||
| 1253 | the type is unit 32. */ | ||
| 1254 | uint16_t flags; | ||
| 1255 | |||
| 1256 | /* Byte offset from the beginning of this table to the first glyph | ||
| 1257 | glyphVariationData. */ | ||
| 1258 | uint32_t offset_to_data; | ||
| 1259 | |||
| 1260 | /* Number of bytes in the glyph variation data. */ | ||
| 1261 | size_t data_size; | ||
| 1262 | |||
| 1263 | /* Byte offsets from the beginning of the glyphVariationData array | ||
| 1264 | to the glyphVariationData for each glyph in the font. The format | ||
| 1265 | of this field is set by the flags field. */ | ||
| 1266 | union { | ||
| 1267 | uint16_t *offset_word; | ||
| 1268 | uint32_t *offset_long; | ||
| 1269 | } u; | ||
| 1270 | |||
| 1271 | /* Other variable length data. */ | ||
| 1272 | sfnt_f2dot14 *global_coords; | ||
| 1273 | unsigned char *glyph_variation_data; | ||
| 1274 | }; | ||
| 1275 | |||
| 1276 | /* Structure repesenting a set of axis coordinates and their | ||
| 1277 | normalized equivalents. | ||
| 1278 | |||
| 1279 | To use this structure, call | ||
| 1280 | |||
| 1281 | sfnt_init_blend (&blend, fvar, gvar) | ||
| 1282 | |||
| 1283 | on a `struct sfnt_blend *', with an appropriate fvar and gvar | ||
| 1284 | table. | ||
| 1285 | |||
| 1286 | Then, fill in blend.coords with the un-normalized coordinates, | ||
| 1287 | and call | ||
| 1288 | |||
| 1289 | sfnt_normalize_blend (&blend) | ||
| 1290 | |||
| 1291 | finally, call sfnt_vary_simple_glyph and related functions. */ | ||
| 1292 | |||
| 1293 | struct sfnt_blend | ||
| 1294 | { | ||
| 1295 | /* The fvar table. This determines the number of elements in each | ||
| 1296 | of the arrays below. */ | ||
| 1297 | struct sfnt_fvar_table *fvar; | ||
| 1298 | |||
| 1299 | /* The gvar table. This provides the glyph variation data. */ | ||
| 1300 | struct sfnt_gvar_table *gvar; | ||
| 1301 | |||
| 1302 | /* The avar table. This provides adjustments to normalized axis | ||
| 1303 | values, and may be NULL. */ | ||
| 1304 | struct sfnt_avar_table *avar; | ||
| 1305 | |||
| 1306 | /* The cvar table. This provides adjustments to CVT values, and may | ||
| 1307 | be NULL. */ | ||
| 1308 | struct sfnt_cvar_table *cvar; | ||
| 1309 | |||
| 1310 | /* Un-normalized coordinates. */ | ||
| 1311 | sfnt_fixed *coords; | ||
| 1312 | |||
| 1313 | /* Normalized coordinates. */ | ||
| 1314 | sfnt_fixed *norm_coords; | ||
| 1315 | }; | ||
| 1316 | |||
| 1317 | struct sfnt_metrics_distortion | ||
| 1318 | { | ||
| 1319 | /* Distortion applied to the origin point. */ | ||
| 1320 | sfnt_fword origin; | ||
| 1321 | |||
| 1322 | /* Distortion applied to the advance point. */ | ||
| 1323 | sfnt_fword advance; | ||
| 1324 | }; | ||
| 1325 | |||
| 1326 | |||
| 1327 | |||
| 969 | #define SFNT_CEIL_FIXED(fixed) \ | 1328 | #define SFNT_CEIL_FIXED(fixed) \ |
| 970 | (!((fixed) & 0177777) ? (fixed) \ | 1329 | (!((fixed) & 0177777) ? (fixed) \ |
| 971 | : ((fixed) + 0200000) & 037777600000) | 1330 | : ((fixed) + 0200000) & 037777600000) |
| @@ -1012,7 +1371,9 @@ extern void sfnt_free_glyph (struct sfnt_glyph *); | |||
| 1012 | #define PROTOTYPE \ | 1371 | #define PROTOTYPE \ |
| 1013 | struct sfnt_glyph *, \ | 1372 | struct sfnt_glyph *, \ |
| 1014 | struct sfnt_head_table *, \ | 1373 | struct sfnt_head_table *, \ |
| 1015 | int, sfnt_get_glyph_proc, \ | 1374 | int, \ |
| 1375 | struct sfnt_glyph_metrics *, \ | ||
| 1376 | sfnt_get_glyph_proc, \ | ||
| 1016 | sfnt_free_glyph_proc, \ | 1377 | sfnt_free_glyph_proc, \ |
| 1017 | void * | 1378 | void * |
| 1018 | extern struct sfnt_glyph_outline *sfnt_build_glyph_outline (PROTOTYPE); | 1379 | extern struct sfnt_glyph_outline *sfnt_build_glyph_outline (PROTOTYPE); |
| @@ -1042,6 +1403,8 @@ extern int sfnt_lookup_glyph_metrics (sfnt_glyph, int, | |||
| 1042 | 1403 | ||
| 1043 | extern void sfnt_scale_metrics (struct sfnt_glyph_metrics *, | 1404 | extern void sfnt_scale_metrics (struct sfnt_glyph_metrics *, |
| 1044 | sfnt_fixed); | 1405 | sfnt_fixed); |
| 1406 | extern void sfnt_scale_metrics_to_pixel_size (struct sfnt_glyph_metrics *, | ||
| 1407 | int, struct sfnt_head_table *); | ||
| 1045 | 1408 | ||
| 1046 | #define PROTOTYPE int, struct sfnt_offset_subtable * | 1409 | #define PROTOTYPE int, struct sfnt_offset_subtable * |
| 1047 | extern struct sfnt_name_table *sfnt_read_name_table (PROTOTYPE); | 1410 | extern struct sfnt_name_table *sfnt_read_name_table (PROTOTYPE); |
| @@ -1061,14 +1424,82 @@ extern char *sfnt_find_metadata (struct sfnt_meta_table *, | |||
| 1061 | 1424 | ||
| 1062 | extern struct sfnt_ttc_header *sfnt_read_ttc_header (int); | 1425 | extern struct sfnt_ttc_header *sfnt_read_ttc_header (int); |
| 1063 | 1426 | ||
| 1427 | |||
| 1428 | |||
| 1429 | #define PROTOTYPE struct sfnt_cmap_format_14 *, int | ||
| 1430 | |||
| 1431 | extern struct sfnt_uvs_context *sfnt_create_uvs_context (PROTOTYPE); | ||
| 1432 | |||
| 1433 | #undef PROTOTYPE | ||
| 1434 | |||
| 1435 | extern void sfnt_free_uvs_context (struct sfnt_uvs_context *); | ||
| 1436 | |||
| 1437 | #define PROTOTYPE struct sfnt_nondefault_uvs_table *, sfnt_char | ||
| 1438 | |||
| 1439 | extern sfnt_glyph sfnt_variation_glyph_for_char (PROTOTYPE); | ||
| 1440 | |||
| 1441 | #undef PROTOTYPE | ||
| 1442 | |||
| 1443 | |||
| 1444 | |||
| 1445 | #ifdef HAVE_MMAP | ||
| 1446 | |||
| 1447 | extern int sfnt_map_table (int, struct sfnt_offset_subtable *, | ||
| 1448 | uint32_t, struct sfnt_mapped_table *); | ||
| 1449 | extern int sfnt_unmap_table (struct sfnt_mapped_table *); | ||
| 1450 | |||
| 1451 | #endif /* HAVE_MMAP */ | ||
| 1452 | |||
| 1453 | |||
| 1454 | |||
| 1455 | extern void *sfnt_read_table (int, struct sfnt_offset_subtable *, | ||
| 1456 | uint32_t, size_t *); | ||
| 1457 | |||
| 1458 | |||
| 1459 | |||
| 1460 | #define PROTOTYPE int, struct sfnt_offset_subtable * | ||
| 1461 | |||
| 1462 | extern struct sfnt_fvar_table *sfnt_read_fvar_table (PROTOTYPE); | ||
| 1463 | extern struct sfnt_gvar_table *sfnt_read_gvar_table (PROTOTYPE); | ||
| 1464 | extern struct sfnt_avar_table *sfnt_read_avar_table (PROTOTYPE); | ||
| 1465 | |||
| 1466 | #undef PROTOTYPE | ||
| 1467 | |||
| 1468 | #define PROTOTYPE \ | ||
| 1469 | int, \ | ||
| 1470 | struct sfnt_offset_subtable *, \ | ||
| 1471 | struct sfnt_fvar_table *, \ | ||
| 1472 | struct sfnt_cvt_table * | ||
| 1473 | |||
| 1474 | extern struct sfnt_cvar_table *sfnt_read_cvar_table (PROTOTYPE); | ||
| 1475 | |||
| 1476 | #undef PROTOTYPE | ||
| 1477 | |||
| 1478 | |||
| 1479 | |||
| 1480 | extern void sfnt_init_blend (struct sfnt_blend *, | ||
| 1481 | struct sfnt_fvar_table *, | ||
| 1482 | struct sfnt_gvar_table *, | ||
| 1483 | struct sfnt_avar_table *, | ||
| 1484 | struct sfnt_cvar_table *); | ||
| 1485 | extern void sfnt_free_blend (struct sfnt_blend *); | ||
| 1486 | extern void sfnt_normalize_blend (struct sfnt_blend *); | ||
| 1487 | |||
| 1488 | |||
| 1489 | |||
| 1490 | extern int sfnt_vary_simple_glyph (struct sfnt_blend *, sfnt_glyph, | ||
| 1491 | struct sfnt_glyph *, | ||
| 1492 | struct sfnt_metrics_distortion *); | ||
| 1493 | extern int sfnt_vary_compound_glyph (struct sfnt_blend *, sfnt_glyph, | ||
| 1494 | struct sfnt_glyph *, | ||
| 1495 | struct sfnt_metrics_distortion *); | ||
| 1496 | |||
| 1064 | #endif /* TEST */ | 1497 | #endif /* TEST */ |
| 1065 | 1498 | ||
| 1066 | 1499 | ||
| 1067 | 1500 | ||
| 1068 | /* TrueType hinting support. */ | 1501 | /* TrueType hinting support. */ |
| 1069 | 1502 | ||
| 1070 | #ifdef SFNT_ENABLE_HINTING | ||
| 1071 | |||
| 1072 | /* Structure definitions for tables used by the TrueType | 1503 | /* Structure definitions for tables used by the TrueType |
| 1073 | interpreter. */ | 1504 | interpreter. */ |
| 1074 | 1505 | ||
| @@ -1107,10 +1538,6 @@ struct sfnt_prep_table | |||
| 1107 | /* 26.6 fixed point type used within the interpreter. */ | 1538 | /* 26.6 fixed point type used within the interpreter. */ |
| 1108 | typedef int32_t sfnt_f26dot6; | 1539 | typedef int32_t sfnt_f26dot6; |
| 1109 | 1540 | ||
| 1110 | /* 2.14 fixed point type used to represent versors of unit | ||
| 1111 | vectors. */ | ||
| 1112 | typedef int16_t sfnt_f2dot14; | ||
| 1113 | |||
| 1114 | /* 18.14 fixed point type used to calculate rounding details. */ | 1541 | /* 18.14 fixed point type used to calculate rounding details. */ |
| 1115 | typedef int32_t sfnt_f18dot14; | 1542 | typedef int32_t sfnt_f18dot14; |
| 1116 | 1543 | ||
| @@ -1479,106 +1906,6 @@ struct sfnt_instructed_outline | |||
| 1479 | 1906 | ||
| 1480 | 1907 | ||
| 1481 | 1908 | ||
| 1482 | /* Unicode Variation Sequence (UVS) support. */ | ||
| 1483 | |||
| 1484 | struct sfnt_default_uvs_table | ||
| 1485 | { | ||
| 1486 | /* Number of ranges that follow. */ | ||
| 1487 | uint32_t num_unicode_value_ranges; | ||
| 1488 | |||
| 1489 | /* Variable length data. */ | ||
| 1490 | struct sfnt_unicode_value_range *ranges; | ||
| 1491 | }; | ||
| 1492 | |||
| 1493 | struct sfnt_unicode_value_range | ||
| 1494 | { | ||
| 1495 | /* First value in this range. */ | ||
| 1496 | unsigned int start_unicode_value; | ||
| 1497 | |||
| 1498 | /* Number of additional values in this range. */ | ||
| 1499 | unsigned char additional_count; | ||
| 1500 | }; | ||
| 1501 | |||
| 1502 | struct sfnt_nondefault_uvs_table | ||
| 1503 | { | ||
| 1504 | /* Number of UVS mappings which follow. */ | ||
| 1505 | uint32_t num_uvs_mappings; | ||
| 1506 | |||
| 1507 | /* Variable length data. */ | ||
| 1508 | struct sfnt_uvs_mapping *mappings; | ||
| 1509 | }; | ||
| 1510 | |||
| 1511 | struct sfnt_uvs_mapping | ||
| 1512 | { | ||
| 1513 | /* Base character value. */ | ||
| 1514 | unsigned int unicode_value; | ||
| 1515 | |||
| 1516 | /* Glyph ID of the base character value. */ | ||
| 1517 | uint16_t base_character_value; | ||
| 1518 | }; | ||
| 1519 | |||
| 1520 | struct sfnt_mapped_variation_selector_record | ||
| 1521 | { | ||
| 1522 | /* The variation selector. */ | ||
| 1523 | unsigned int selector; | ||
| 1524 | |||
| 1525 | /* Its default UVS table. */ | ||
| 1526 | struct sfnt_default_uvs_table *default_uvs; | ||
| 1527 | |||
| 1528 | /* Its nondefault UVS table. */ | ||
| 1529 | struct sfnt_nondefault_uvs_table *nondefault_uvs; | ||
| 1530 | }; | ||
| 1531 | |||
| 1532 | /* Structure describing a single offset to load into a variation | ||
| 1533 | selection context. */ | ||
| 1534 | |||
| 1535 | struct sfnt_table_offset_rec | ||
| 1536 | { | ||
| 1537 | /* The offset from the start of the font file. */ | ||
| 1538 | off_t offset; | ||
| 1539 | |||
| 1540 | /* Whether or not the offset points to a non-default UVS table. */ | ||
| 1541 | bool is_nondefault_table; | ||
| 1542 | |||
| 1543 | /* Pointer to the UVS table. */ | ||
| 1544 | void *table; | ||
| 1545 | }; | ||
| 1546 | |||
| 1547 | struct sfnt_uvs_context | ||
| 1548 | { | ||
| 1549 | /* Number of records and tables. */ | ||
| 1550 | size_t num_records, nmemb; | ||
| 1551 | |||
| 1552 | /* Array of UVS tables. */ | ||
| 1553 | struct sfnt_table_offset_rec *tables; | ||
| 1554 | |||
| 1555 | /* Array of variation selector records mapped to | ||
| 1556 | their corresponding tables. */ | ||
| 1557 | struct sfnt_mapped_variation_selector_record *records; | ||
| 1558 | }; | ||
| 1559 | |||
| 1560 | |||
| 1561 | |||
| 1562 | #if defined HAVE_MMAP && !defined TEST | ||
| 1563 | |||
| 1564 | /* Memory mapping support. */ | ||
| 1565 | |||
| 1566 | struct sfnt_mapped_table | ||
| 1567 | { | ||
| 1568 | /* Pointer to table data. */ | ||
| 1569 | void *data; | ||
| 1570 | |||
| 1571 | /* Pointer to table mapping. */ | ||
| 1572 | void *mapping; | ||
| 1573 | |||
| 1574 | /* Size of mapped data and size of mapping. */ | ||
| 1575 | size_t length, size; | ||
| 1576 | }; | ||
| 1577 | |||
| 1578 | #endif /* HAVE_MMAP && !TEST */ | ||
| 1579 | |||
| 1580 | |||
| 1581 | |||
| 1582 | /* Functions used to read tables used by the TrueType interpreter. */ | 1909 | /* Functions used to read tables used by the TrueType interpreter. */ |
| 1583 | 1910 | ||
| 1584 | #ifndef TEST | 1911 | #ifndef TEST |
| @@ -1653,39 +1980,11 @@ extern const char *sfnt_interpret_compound_glyph (PROTOTYPE); | |||
| 1653 | 1980 | ||
| 1654 | 1981 | ||
| 1655 | 1982 | ||
| 1656 | #define PROTOTYPE struct sfnt_cmap_format_14 *, int | 1983 | extern void sfnt_vary_interpreter (struct sfnt_interpreter *, |
| 1657 | 1984 | struct sfnt_blend *); | |
| 1658 | extern struct sfnt_uvs_context *sfnt_create_uvs_context (PROTOTYPE); | ||
| 1659 | |||
| 1660 | #undef PROTOTYPE | ||
| 1661 | |||
| 1662 | extern void sfnt_free_uvs_context (struct sfnt_uvs_context *); | ||
| 1663 | |||
| 1664 | #define PROTOTYPE struct sfnt_nondefault_uvs_table *, sfnt_char | ||
| 1665 | |||
| 1666 | extern sfnt_glyph sfnt_variation_glyph_for_char (PROTOTYPE); | ||
| 1667 | |||
| 1668 | #undef PROTOTYPE | ||
| 1669 | |||
| 1670 | |||
| 1671 | |||
| 1672 | #ifdef HAVE_MMAP | ||
| 1673 | |||
| 1674 | extern int sfnt_map_table (int, struct sfnt_offset_subtable *, | ||
| 1675 | uint32_t, struct sfnt_mapped_table *); | ||
| 1676 | extern int sfnt_unmap_table (struct sfnt_mapped_table *); | ||
| 1677 | |||
| 1678 | #endif /* HAVE_MMAP */ | ||
| 1679 | |||
| 1680 | |||
| 1681 | |||
| 1682 | extern void *sfnt_read_table (int, struct sfnt_offset_subtable *, | ||
| 1683 | uint32_t, size_t *); | ||
| 1684 | 1985 | ||
| 1685 | #endif /* TEST */ | 1986 | #endif /* TEST */ |
| 1686 | 1987 | ||
| 1687 | 1988 | ||
| 1688 | 1989 | ||
| 1689 | #endif /* SFNT_ENABLE_HINTING */ | ||
| 1690 | |||
| 1691 | #endif /* _SFNT_H_ */ | 1990 | #endif /* _SFNT_H_ */ |
diff --git a/src/sfntfont.c b/src/sfntfont.c index 500256d6fb4..e4579d62154 100644 --- a/src/sfntfont.c +++ b/src/sfntfont.c | |||
| @@ -1688,6 +1688,8 @@ sfntfont_dereference_outline (struct sfnt_glyph_outline *outline) | |||
| 1688 | 1688 | ||
| 1689 | If INTERPRETER is non-NULL, then possibly use the unscaled glyph | 1689 | If INTERPRETER is non-NULL, then possibly use the unscaled glyph |
| 1690 | metrics in METRICS and the interpreter STATE to instruct the glyph. | 1690 | metrics in METRICS and the interpreter STATE to instruct the glyph. |
| 1691 | Otherwise, METRICS must contain scaled glyph metrics used to | ||
| 1692 | compute the origin point of the outline. | ||
| 1691 | 1693 | ||
| 1692 | Return the outline with an incremented reference count and enter | 1694 | Return the outline with an incremented reference count and enter |
| 1693 | the generated outline into CACHE upon success, possibly discarding | 1695 | the generated outline into CACHE upon success, possibly discarding |
| @@ -1714,6 +1716,7 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code, | |||
| 1714 | struct sfntfont_get_glyph_outline_dcontext dcontext; | 1716 | struct sfntfont_get_glyph_outline_dcontext dcontext; |
| 1715 | struct sfnt_instructed_outline *value; | 1717 | struct sfnt_instructed_outline *value; |
| 1716 | const char *error; | 1718 | const char *error; |
| 1719 | struct sfnt_glyph_metrics temp; | ||
| 1717 | 1720 | ||
| 1718 | start = cache->next; | 1721 | start = cache->next; |
| 1719 | 1722 | ||
| @@ -1784,10 +1787,31 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code, | |||
| 1784 | } | 1787 | } |
| 1785 | 1788 | ||
| 1786 | if (!outline) | 1789 | if (!outline) |
| 1787 | outline = sfnt_build_glyph_outline (glyph, head, pixel_size, | 1790 | { |
| 1788 | sfntfont_get_glyph, | 1791 | /* If INTERPRETER is NULL, METRICS contains scaled metrics. */ |
| 1789 | sfntfont_free_glyph, | 1792 | |
| 1790 | &dcontext); | 1793 | if (!interpreter) |
| 1794 | outline = sfnt_build_glyph_outline (glyph, head, pixel_size, | ||
| 1795 | metrics, | ||
| 1796 | sfntfont_get_glyph, | ||
| 1797 | sfntfont_free_glyph, | ||
| 1798 | &dcontext); | ||
| 1799 | else | ||
| 1800 | { | ||
| 1801 | /* But otherwise, they are unscaled, and must be scaled | ||
| 1802 | before being used. */ | ||
| 1803 | |||
| 1804 | temp = *metrics; | ||
| 1805 | sfnt_scale_metrics_to_pixel_size (&temp, pixel_size, | ||
| 1806 | head); | ||
| 1807 | outline = sfnt_build_glyph_outline (glyph, head, pixel_size, | ||
| 1808 | &temp, | ||
| 1809 | sfntfont_get_glyph, | ||
| 1810 | sfntfont_free_glyph, | ||
| 1811 | &dcontext); | ||
| 1812 | } | ||
| 1813 | } | ||
| 1814 | |||
| 1791 | xfree (glyph); | 1815 | xfree (glyph); |
| 1792 | 1816 | ||
| 1793 | if (!outline) | 1817 | if (!outline) |
| @@ -2689,8 +2713,8 @@ sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph, | |||
| 2689 | font->hmtx, font->hhea, | 2713 | font->hmtx, font->hhea, |
| 2690 | font->maxp, | 2714 | font->maxp, |
| 2691 | font->loca_short, | 2715 | font->loca_short, |
| 2692 | font->loca_long, NULL, NULL, | 2716 | font->loca_long, NULL, |
| 2693 | NULL); | 2717 | &metrics, NULL); |
| 2694 | 2718 | ||
| 2695 | if (!outline) | 2719 | if (!outline) |
| 2696 | return 1; | 2720 | return 1; |