diff options
| -rw-r--r-- | src/sfnt.c | 1809 | ||||
| -rw-r--r-- | src/sfnt.h | 24 |
2 files changed, 1795 insertions, 38 deletions
diff --git a/src/sfnt.c b/src/sfnt.c index bdd713aa016..21b2ea96e1c 100644 --- a/src/sfnt.c +++ b/src/sfnt.c | |||
| @@ -150,6 +150,9 @@ static uint32_t sfnt_table_names[] = | |||
| 150 | [SFNT_TABLE_CVT ] = 0x63767420, | 150 | [SFNT_TABLE_CVT ] = 0x63767420, |
| 151 | [SFNT_TABLE_FPGM] = 0x6670676d, | 151 | [SFNT_TABLE_FPGM] = 0x6670676d, |
| 152 | [SFNT_TABLE_PREP] = 0x70726570, | 152 | [SFNT_TABLE_PREP] = 0x70726570, |
| 153 | [SFNT_TABLE_FVAR] = 0x66766172, | ||
| 154 | [SFNT_TABLE_GVAR] = 0x67766172, | ||
| 155 | [SFNT_TABLE_CVAR] = 0x63766172, | ||
| 153 | }; | 156 | }; |
| 154 | 157 | ||
| 155 | /* Swap values from TrueType to system byte order. */ | 158 | /* Swap values from TrueType to system byte order. */ |
| @@ -1614,7 +1617,7 @@ sfnt_read_maxp_table (int fd, struct sfnt_offset_subtable *subtable) | |||
| 1614 | directory->length or sizeof *maxp bytes into it, whichever is | 1617 | directory->length or sizeof *maxp bytes into it, whichever is |
| 1615 | smaller. */ | 1618 | smaller. */ |
| 1616 | 1619 | ||
| 1617 | maxp = malloc (sizeof *maxp); | 1620 | maxp = xmalloc (sizeof *maxp); |
| 1618 | size = MIN (directory->length, sizeof *maxp); | 1621 | size = MIN (directory->length, sizeof *maxp); |
| 1619 | rc = read (fd, maxp, size); | 1622 | rc = read (fd, maxp, size); |
| 1620 | 1623 | ||
| @@ -1917,6 +1920,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, | |||
| 1917 | { | 1920 | { |
| 1918 | glyph->simple = NULL; | 1921 | glyph->simple = NULL; |
| 1919 | xfree (simple); | 1922 | xfree (simple); |
| 1923 | return; | ||
| 1920 | } | 1924 | } |
| 1921 | 1925 | ||
| 1922 | /* Repeat the current flag until | 1926 | /* Repeat the current flag until |
| @@ -4227,8 +4231,10 @@ sfnt_fill_span (struct sfnt_raster *raster, sfnt_fixed y, | |||
| 4227 | } | 4231 | } |
| 4228 | 4232 | ||
| 4229 | /* Clear coverage info for first pixel. Compute coverage for center | 4233 | /* Clear coverage info for first pixel. Compute coverage for center |
| 4230 | pixels. */ | 4234 | pixels. Note that SFNT_POLY_SAMPLE is used and not |
| 4231 | w = coverage[SFNT_POLY_MASK]; | 4235 | SFNT_POLY_MASK, because coverage has a blank column at the |
| 4236 | start. */ | ||
| 4237 | w = coverage[SFNT_POLY_SAMPLE]; | ||
| 4232 | 4238 | ||
| 4233 | /* Fill pixels between left and right. */ | 4239 | /* Fill pixels between left and right. */ |
| 4234 | while (left + SFNT_POLY_MASK < right) | 4240 | while (left + SFNT_POLY_MASK < right) |
| @@ -8080,6 +8086,7 @@ sfnt_normalize_vector (sfnt_f26dot6 vx, sfnt_f26dot6 vy, | |||
| 8080 | /* If vx and vy are both zero, then just project | 8086 | /* If vx and vy are both zero, then just project |
| 8081 | horizontally. */ | 8087 | horizontally. */ |
| 8082 | 8088 | ||
| 8089 | fail: | ||
| 8083 | vector->x = 04000; | 8090 | vector->x = 04000; |
| 8084 | vector->y = 0; | 8091 | vector->y = 0; |
| 8085 | return; | 8092 | return; |
| @@ -8113,6 +8120,10 @@ sfnt_normalize_vector (sfnt_f26dot6 vx, sfnt_f26dot6 vy, | |||
| 8113 | /* Get hypotenuse of the triangle from vx, 0, to 0, vy. */ | 8120 | /* Get hypotenuse of the triangle from vx, 0, to 0, vy. */ |
| 8114 | magnitude = sfnt_sqrt_fixed (n); | 8121 | magnitude = sfnt_sqrt_fixed (n); |
| 8115 | 8122 | ||
| 8123 | /* Avoid division by zero. */ | ||
| 8124 | if (!magnitude) | ||
| 8125 | goto fail; | ||
| 8126 | |||
| 8116 | /* Long division.. eek! */ | 8127 | /* Long division.. eek! */ |
| 8117 | vector->x = (sfnt_div_fixed (vx * 1024, magnitude) >> 2); | 8128 | vector->x = (sfnt_div_fixed (vx * 1024, magnitude) >> 2); |
| 8118 | vector->y = (sfnt_div_fixed (vy * 1024, magnitude) >> 2); | 8129 | vector->y = (sfnt_div_fixed (vy * 1024, magnitude) >> 2); |
| @@ -8169,8 +8180,8 @@ sfnt_line_to_vector (struct sfnt_interpreter *interpreter, | |||
| 8169 | relative to the projection or dual projection vector. | 8180 | relative to the projection or dual projection vector. |
| 8170 | 8181 | ||
| 8171 | Return the distance of P1 and P2 relative to their original | 8182 | Return the distance of P1 and P2 relative to their original |
| 8172 | un-instructed positions should OPCODE be 0x49, and to their | 8183 | un-instructed positions should OPCODE be 0x4A, and to their |
| 8173 | instructed positions should OPCODE be 0x4A. */ | 8184 | instructed positions should OPCODE be 0x49. */ |
| 8174 | 8185 | ||
| 8175 | static sfnt_f26dot6 | 8186 | static sfnt_f26dot6 |
| 8176 | sfnt_measure_distance (struct sfnt_interpreter *interpreter, | 8187 | sfnt_measure_distance (struct sfnt_interpreter *interpreter, |
| @@ -8188,25 +8199,9 @@ sfnt_measure_distance (struct sfnt_interpreter *interpreter, | |||
| 8188 | sfnt_address_zp1 (interpreter, p2, &p2x, &p2y, | 8199 | sfnt_address_zp1 (interpreter, p2, &p2x, &p2y, |
| 8189 | &p2_original_x, &p2_original_y); | 8200 | &p2_original_x, &p2_original_y); |
| 8190 | 8201 | ||
| 8191 | if (opcode == 0x49) | 8202 | if (opcode == 0x4A) |
| 8192 | { | 8203 | return DUAL_PROJECT (sfnt_sub (p1_original_x, p2_original_x), |
| 8193 | /* When measuring in the glyph zone, measure the distance using | 8204 | sfnt_sub (p1_original_y, p2_original_y)); |
| 8194 | the dual projection vector, relative to the ``original | ||
| 8195 | original outlines''. | ||
| 8196 | |||
| 8197 | This is not written down anywhere, leading you to believe | ||
| 8198 | that the distance is measured using the scaled outline prior | ||
| 8199 | to instructing. */ | ||
| 8200 | |||
| 8201 | if (interpreter->state.zp0 == 1 | ||
| 8202 | && interpreter->state.zp1 == 1) | ||
| 8203 | return sfnt_div_fixed (DUAL_PROJECT (sfnt_sub (p1x, p2x), | ||
| 8204 | sfnt_sub (p1y, p2y)), | ||
| 8205 | interpreter->scale); | ||
| 8206 | |||
| 8207 | return DUAL_PROJECT (sfnt_sub (p1x, p2x), | ||
| 8208 | sfnt_sub (p1y, p2y)); | ||
| 8209 | } | ||
| 8210 | 8205 | ||
| 8211 | return PROJECT (sfnt_sub (p1x, p2x), | 8206 | return PROJECT (sfnt_sub (p1x, p2x), |
| 8212 | sfnt_sub (p1y, p2y)); | 8207 | sfnt_sub (p1y, p2y)); |
| @@ -9238,7 +9233,7 @@ sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by) | |||
| 9238 | yy = xx >> 63; | 9233 | yy = xx >> 63; |
| 9239 | xx += 0x2000 + yy; | 9234 | xx += 0x2000 + yy; |
| 9240 | 9235 | ||
| 9241 | return (int32_t) (yy / (2 << 14)); | 9236 | return (int32_t) (xx / (2 << 14)); |
| 9242 | #endif | 9237 | #endif |
| 9243 | } | 9238 | } |
| 9244 | 9239 | ||
| @@ -11454,6 +11449,8 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph, | |||
| 11454 | struct sfnt_instructed_outline *value; | 11449 | struct sfnt_instructed_outline *value; |
| 11455 | struct sfnt_glyph_metrics sub_metrics; | 11450 | struct sfnt_glyph_metrics sub_metrics; |
| 11456 | 11451 | ||
| 11452 | error = NULL; | ||
| 11453 | |||
| 11457 | /* Set up the base index. This is the index from where on point | 11454 | /* Set up the base index. This is the index from where on point |
| 11458 | renumbering starts. | 11455 | renumbering starts. |
| 11459 | 11456 | ||
| @@ -12431,6 +12428,1656 @@ sfnt_read_table (int fd, struct sfnt_offset_subtable *subtable, | |||
| 12431 | 12428 | ||
| 12432 | #endif /* !TEST */ | 12429 | #endif /* !TEST */ |
| 12433 | 12430 | ||
| 12431 | #ifdef TEST | ||
| 12432 | |||
| 12433 | |||
| 12434 | |||
| 12435 | /* Glyph variations. Instead of defining separate fonts for each | ||
| 12436 | combination of weight, width and slant (bold, condensed, italic, | ||
| 12437 | etc), some fonts specify a list of ``variation axes'', each of | ||
| 12438 | which determines one delta to apply to each point in every | ||
| 12439 | glyph. | ||
| 12440 | |||
| 12441 | This optional information is specified in the `fvar' (font | ||
| 12442 | variation), `gvar' (glyph variation) and `cvar' (CVT variation) | ||
| 12443 | tables in a font file. */ | ||
| 12444 | |||
| 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 | ||
| 12517 | specified in SUBTABLE. | ||
| 12518 | |||
| 12519 | Return the fvar table upon success, else NULL. */ | ||
| 12520 | |||
| 12521 | static struct sfnt_fvar_table * | ||
| 12522 | sfnt_read_fvar_table (int fd, struct sfnt_offset_subtable *subtable) | ||
| 12523 | { | ||
| 12524 | struct sfnt_table_directory *directory; | ||
| 12525 | struct sfnt_fvar_table *fvar; | ||
| 12526 | ssize_t rc; | ||
| 12527 | size_t min_bytes, ps_size, non_ps_size, temp, pad; | ||
| 12528 | off_t offset; | ||
| 12529 | int i, j; | ||
| 12530 | char *buffer; | ||
| 12531 | sfnt_fixed *coords; | ||
| 12532 | |||
| 12533 | /* Find the table in the directory. */ | ||
| 12534 | |||
| 12535 | directory = sfnt_find_table (subtable, SFNT_TABLE_FVAR); | ||
| 12536 | |||
| 12537 | if (!directory) | ||
| 12538 | return NULL; | ||
| 12539 | |||
| 12540 | min_bytes = SFNT_ENDOF (struct sfnt_fvar_table, | ||
| 12541 | instance_size, uint16_t); | ||
| 12542 | |||
| 12543 | /* Check that the length is at least min_bytes. */ | ||
| 12544 | if (directory->length < min_bytes) | ||
| 12545 | return NULL; | ||
| 12546 | |||
| 12547 | /* Seek to the location given in the directory. */ | ||
| 12548 | if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1) | ||
| 12549 | return NULL; | ||
| 12550 | |||
| 12551 | /* Allocate enough to hold the fvar table header. */ | ||
| 12552 | fvar = xmalloc (sizeof *fvar); | ||
| 12553 | |||
| 12554 | /* Read the fvar table header. */ | ||
| 12555 | buffer = NULL; | ||
| 12556 | rc = read (fd, fvar, min_bytes); | ||
| 12557 | if (rc != min_bytes) | ||
| 12558 | goto bail; | ||
| 12559 | |||
| 12560 | /* Swap what was read. */ | ||
| 12561 | sfnt_swap16 (&fvar->major_version); | ||
| 12562 | sfnt_swap16 (&fvar->minor_version); | ||
| 12563 | sfnt_swap16 (&fvar->offset_to_data); | ||
| 12564 | sfnt_swap16 (&fvar->count_size_pairs); | ||
| 12565 | sfnt_swap16 (&fvar->axis_count); | ||
| 12566 | sfnt_swap16 (&fvar->axis_size); | ||
| 12567 | sfnt_swap16 (&fvar->instance_count); | ||
| 12568 | sfnt_swap16 (&fvar->instance_size); | ||
| 12569 | |||
| 12570 | /* major_version should be 1, and minor_version 0. */ | ||
| 12571 | |||
| 12572 | if (fvar->major_version != 1 || fvar->minor_version) | ||
| 12573 | goto bail; | ||
| 12574 | |||
| 12575 | /* count_size_pairs should be more than 2. */ | ||
| 12576 | |||
| 12577 | if (fvar->count_size_pairs < 2) | ||
| 12578 | goto bail; | ||
| 12579 | |||
| 12580 | /* Don't try to read tables where the axis format differs. */ | ||
| 12581 | |||
| 12582 | if (fvar->axis_size != 20) | ||
| 12583 | goto bail; | ||
| 12584 | |||
| 12585 | /* The instance size must either be 2 * sizeof (uint16_t) + | ||
| 12586 | axisCount * sizeof (sfnt_fixed), meaning there is no PostScript | ||
| 12587 | name identifier, or 3 * sizeof (uint16_t) + axisCount * sizeof | ||
| 12588 | (sfnt_fixed), meaning there is. */ | ||
| 12589 | |||
| 12590 | if (INT_MULTIPLY_WRAPV (fvar->axis_count, sizeof (sfnt_fixed), | ||
| 12591 | &temp) | ||
| 12592 | || INT_ADD_WRAPV (2 * sizeof (uint16_t), temp, &non_ps_size)) | ||
| 12593 | goto bail; | ||
| 12594 | |||
| 12595 | if (INT_MULTIPLY_WRAPV (fvar->axis_count, sizeof (sfnt_fixed), | ||
| 12596 | &temp) | ||
| 12597 | || INT_ADD_WRAPV (3 * sizeof (uint16_t), temp, &ps_size)) | ||
| 12598 | goto bail; | ||
| 12599 | |||
| 12600 | if (fvar->instance_size != non_ps_size | ||
| 12601 | && fvar->instance_size != ps_size) | ||
| 12602 | goto bail; | ||
| 12603 | |||
| 12604 | /* Now compute the offset of the axis data from the start of the | ||
| 12605 | font file. */ | ||
| 12606 | |||
| 12607 | if (INT_ADD_WRAPV (fvar->offset_to_data, directory->offset, | ||
| 12608 | &offset)) | ||
| 12609 | goto bail; | ||
| 12610 | |||
| 12611 | /* Seek there. */ | ||
| 12612 | |||
| 12613 | if (lseek (fd, offset, SEEK_SET) != offset) | ||
| 12614 | goto bail; | ||
| 12615 | |||
| 12616 | min_bytes = sizeof *fvar; | ||
| 12617 | |||
| 12618 | /* Now, read each axis and instance. Calculate how much extra data | ||
| 12619 | needs to be allocated for the axes and instances: this is | ||
| 12620 | fvar->axis_count * sizeof (struct sfnt_variation_axis), some | ||
| 12621 | padding, and finally fvar->instance_count * sizeof (struct | ||
| 12622 | sfnt_instance) + sizeof (sfnt_fixed) * fvar->instance_count * | ||
| 12623 | fvar->axis_count. */ | ||
| 12624 | |||
| 12625 | if (INT_MULTIPLY_WRAPV (fvar->axis_count, sizeof *fvar->axis, | ||
| 12626 | &temp) | ||
| 12627 | || INT_ADD_WRAPV (min_bytes, temp, &min_bytes)) | ||
| 12628 | goto bail; | ||
| 12629 | |||
| 12630 | pad = alignof (struct sfnt_variation_axis); | ||
| 12631 | pad -= min_bytes & (pad - 1); | ||
| 12632 | |||
| 12633 | if (INT_ADD_WRAPV (min_bytes, pad, &min_bytes)) | ||
| 12634 | goto bail; | ||
| 12635 | |||
| 12636 | if (INT_MULTIPLY_WRAPV (fvar->instance_count, | ||
| 12637 | sizeof *fvar->instance, | ||
| 12638 | &temp) | ||
| 12639 | || INT_ADD_WRAPV (min_bytes, temp, &min_bytes)) | ||
| 12640 | goto bail; | ||
| 12641 | |||
| 12642 | if (INT_MULTIPLY_WRAPV (fvar->instance_count, | ||
| 12643 | sizeof *fvar->instance->coords, | ||
| 12644 | &temp) | ||
| 12645 | || INT_MULTIPLY_WRAPV (temp, fvar->axis_count, &temp) | ||
| 12646 | || INT_ADD_WRAPV (min_bytes, temp, &min_bytes)) | ||
| 12647 | goto bail; | ||
| 12648 | |||
| 12649 | /* Reallocate fvar. */ | ||
| 12650 | fvar = xrealloc (fvar, min_bytes); | ||
| 12651 | |||
| 12652 | /* Fill in offsets. */ | ||
| 12653 | fvar->axis = (struct sfnt_variation_axis *) (fvar + 1); | ||
| 12654 | fvar->instance | ||
| 12655 | = (struct sfnt_instance *) (((char *) (fvar->axis | ||
| 12656 | + fvar->axis_count)) | ||
| 12657 | + pad); | ||
| 12658 | |||
| 12659 | /* Read axes. */ | ||
| 12660 | |||
| 12661 | if (directory->length - SFNT_ENDOF (struct sfnt_fvar_table, | ||
| 12662 | instance_size, uint16_t) | ||
| 12663 | < sizeof *fvar->axis * fvar->axis_count) | ||
| 12664 | goto bail; | ||
| 12665 | |||
| 12666 | rc = read (fd, fvar->axis, sizeof *fvar->axis * fvar->axis_count); | ||
| 12667 | if (rc != sizeof *fvar->axis * fvar->axis_count) | ||
| 12668 | goto bail; | ||
| 12669 | |||
| 12670 | /* Swap each axis. */ | ||
| 12671 | |||
| 12672 | for (i = 0; i < fvar->axis_count; ++i) | ||
| 12673 | { | ||
| 12674 | sfnt_swap32 (&fvar->axis[i].axis_tag); | ||
| 12675 | sfnt_swap32 (&fvar->axis[i].min_value); | ||
| 12676 | sfnt_swap32 (&fvar->axis[i].default_value); | ||
| 12677 | sfnt_swap32 (&fvar->axis[i].max_value); | ||
| 12678 | sfnt_swap16 (&fvar->axis[i].flags); | ||
| 12679 | sfnt_swap16 (&fvar->axis[i].name_id); | ||
| 12680 | } | ||
| 12681 | |||
| 12682 | /* Read each instance. */ | ||
| 12683 | |||
| 12684 | if (fvar->instance_size < 1024 * 16) | ||
| 12685 | buffer = alloca (fvar->instance_size); | ||
| 12686 | else | ||
| 12687 | buffer = xmalloc (fvar->instance_size); | ||
| 12688 | |||
| 12689 | coords = (sfnt_fixed *) (fvar->instance + fvar->instance_count); | ||
| 12690 | |||
| 12691 | for (i = 0; i < fvar->instance_count; ++i) | ||
| 12692 | { | ||
| 12693 | rc = read (fd, buffer, fvar->instance_size); | ||
| 12694 | if (rc != fvar->instance_size) | ||
| 12695 | goto bail; | ||
| 12696 | |||
| 12697 | /* Fill in various fields. */ | ||
| 12698 | |||
| 12699 | fvar->instance[i].name_id = *((uint16_t *) buffer); | ||
| 12700 | fvar->instance[i].flags = *((uint16_t *) buffer + 1); | ||
| 12701 | fvar->instance[i].ps_name_id = 0; | ||
| 12702 | |||
| 12703 | sfnt_swap16 (&fvar->instance[i].name_id); | ||
| 12704 | sfnt_swap16 (&fvar->instance[i].flags); | ||
| 12705 | |||
| 12706 | /* Read coordinates. */ | ||
| 12707 | |||
| 12708 | fvar->instance[i].coords = coords; | ||
| 12709 | coords += fvar->axis_count; | ||
| 12710 | |||
| 12711 | memcpy (fvar->instance[i].coords, buffer + 4, | ||
| 12712 | sizeof *fvar->instance[i].coords * fvar->axis_count); | ||
| 12713 | |||
| 12714 | /* Swap coordinates. */ | ||
| 12715 | |||
| 12716 | for (j = 0; j < fvar->axis_count; ++j) | ||
| 12717 | sfnt_swap32 (&fvar->instance[i].coords[j]); | ||
| 12718 | |||
| 12719 | /* Read the PostScript name ID if necessary. If not, set it to | ||
| 12720 | nil. */ | ||
| 12721 | |||
| 12722 | if (fvar->instance_size == ps_size) | ||
| 12723 | { | ||
| 12724 | fvar->instance[i].ps_name_id | ||
| 12725 | = *(uint16_t *) (buffer + 4 + (sizeof *fvar->instance[i].coords | ||
| 12726 | * fvar->axis_count)); | ||
| 12727 | sfnt_swap16 (&fvar->instance[i].ps_name_id); | ||
| 12728 | } | ||
| 12729 | } | ||
| 12730 | |||
| 12731 | /* Free the temporary buffer. */ | ||
| 12732 | if (buffer && fvar->instance_size >= 1024 * 16) | ||
| 12733 | xfree (buffer); | ||
| 12734 | |||
| 12735 | /* Return the fvar table. */ | ||
| 12736 | return fvar; | ||
| 12737 | |||
| 12738 | bail: | ||
| 12739 | if (buffer && fvar->instance_size >= 1024 * 16) | ||
| 12740 | xfree (buffer); | ||
| 12741 | |||
| 12742 | xfree (fvar); | ||
| 12743 | return NULL; | ||
| 12744 | } | ||
| 12745 | |||
| 12746 | |||
| 12747 | |||
| 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 | ||
| 12797 | specified in SUBTABLE. | ||
| 12798 | |||
| 12799 | Return the gvar table upon success, else NULL. */ | ||
| 12800 | |||
| 12801 | static struct sfnt_gvar_table * | ||
| 12802 | sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable) | ||
| 12803 | { | ||
| 12804 | struct sfnt_table_directory *directory; | ||
| 12805 | struct sfnt_gvar_table *gvar; | ||
| 12806 | ssize_t rc; | ||
| 12807 | size_t min_bytes, off_size, coordinate_size, data_size; | ||
| 12808 | int i; | ||
| 12809 | off_t offset; | ||
| 12810 | |||
| 12811 | /* Find the table in the directory. */ | ||
| 12812 | |||
| 12813 | directory = sfnt_find_table (subtable, SFNT_TABLE_GVAR); | ||
| 12814 | |||
| 12815 | if (!directory) | ||
| 12816 | return NULL; | ||
| 12817 | |||
| 12818 | min_bytes = SFNT_ENDOF (struct sfnt_gvar_table, | ||
| 12819 | offset_to_data, uint32_t); | ||
| 12820 | |||
| 12821 | /* Check that the length is at least min_bytes. */ | ||
| 12822 | if (directory->length < min_bytes) | ||
| 12823 | return NULL; | ||
| 12824 | |||
| 12825 | /* Seek to the location given in the directory. */ | ||
| 12826 | if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1) | ||
| 12827 | return NULL; | ||
| 12828 | |||
| 12829 | /* Allocate enough to hold the gvar table header. */ | ||
| 12830 | gvar = xmalloc (sizeof *gvar); | ||
| 12831 | |||
| 12832 | /* Read the gvar table header. */ | ||
| 12833 | rc = read (fd, gvar, min_bytes); | ||
| 12834 | if (rc != min_bytes) | ||
| 12835 | goto bail; | ||
| 12836 | |||
| 12837 | /* Swap what was read. */ | ||
| 12838 | sfnt_swap16 (&gvar->version); | ||
| 12839 | sfnt_swap16 (&gvar->reserved); | ||
| 12840 | sfnt_swap16 (&gvar->axis_count); | ||
| 12841 | sfnt_swap16 (&gvar->shared_coord_count); | ||
| 12842 | sfnt_swap32 (&gvar->offset_to_coord); | ||
| 12843 | sfnt_swap16 (&gvar->glyph_count); | ||
| 12844 | sfnt_swap16 (&gvar->flags); | ||
| 12845 | sfnt_swap32 (&gvar->offset_to_data); | ||
| 12846 | |||
| 12847 | if (gvar->version != 1) | ||
| 12848 | goto bail; | ||
| 12849 | |||
| 12850 | if (gvar->offset_to_data > directory->length) | ||
| 12851 | goto bail; | ||
| 12852 | |||
| 12853 | /* Figure out the size required for the offset array. Note that | ||
| 12854 | there is one extra offset at the end of the array to mark the | ||
| 12855 | size of the last glyph. */ | ||
| 12856 | |||
| 12857 | if (gvar->flags & 1) | ||
| 12858 | /* Offsets are long words. */ | ||
| 12859 | off_size = sizeof (uint32_t) * (gvar->glyph_count + 1); | ||
| 12860 | else | ||
| 12861 | /* Offsets are words. */ | ||
| 12862 | off_size = sizeof (uint16_t) * (gvar->glyph_count + 1); | ||
| 12863 | |||
| 12864 | /* Now figure out the size of the shared coordinates. */ | ||
| 12865 | coordinate_size = (gvar->shared_coord_count * gvar->axis_count | ||
| 12866 | * sizeof (uint16_t)); | ||
| 12867 | |||
| 12868 | /* And the size of the glyph variation data. */ | ||
| 12869 | data_size = directory->length - gvar->offset_to_data; | ||
| 12870 | |||
| 12871 | /* Wraparound. */ | ||
| 12872 | if (data_size > directory->length) | ||
| 12873 | goto bail; | ||
| 12874 | |||
| 12875 | /* Figure out how big gvar needs to be. */ | ||
| 12876 | if (INT_ADD_WRAPV (sizeof *gvar, coordinate_size, &min_bytes) | ||
| 12877 | || INT_ADD_WRAPV (min_bytes, off_size, &min_bytes) | ||
| 12878 | || INT_ADD_WRAPV (min_bytes, data_size, &min_bytes)) | ||
| 12879 | goto bail; | ||
| 12880 | |||
| 12881 | /* Now allocate enough for all of this extra data. */ | ||
| 12882 | gvar = xrealloc (gvar, min_bytes); | ||
| 12883 | |||
| 12884 | /* Start reading offsets. */ | ||
| 12885 | |||
| 12886 | if (!(gvar->flags & 1)) | ||
| 12887 | { | ||
| 12888 | gvar->u.offset_word = (uint16_t *) (gvar + 1); | ||
| 12889 | rc = read (fd, gvar->u.offset_word, off_size); | ||
| 12890 | if (rc != off_size) | ||
| 12891 | goto bail; | ||
| 12892 | |||
| 12893 | for (i = 0; i <= gvar->glyph_count; ++i) | ||
| 12894 | sfnt_swap16 (&gvar->u.offset_word[i]); | ||
| 12895 | } | ||
| 12896 | else | ||
| 12897 | { | ||
| 12898 | gvar->u.offset_long = (uint32_t *) (gvar + 1); | ||
| 12899 | rc = read (fd, gvar->u.offset_long, off_size); | ||
| 12900 | if (rc != off_size) | ||
| 12901 | goto bail; | ||
| 12902 | |||
| 12903 | for (i = 0; i <= gvar->glyph_count; ++i) | ||
| 12904 | sfnt_swap32 (&gvar->u.offset_long[i]); | ||
| 12905 | } | ||
| 12906 | |||
| 12907 | /* Start reading shared coordinates. */ | ||
| 12908 | |||
| 12909 | gvar->global_coords = ((sfnt_f2dot14 *) ((char *) gvar + off_size)); | ||
| 12910 | |||
| 12911 | if (gvar->shared_coord_count) | ||
| 12912 | { | ||
| 12913 | if (INT_ADD_WRAPV (gvar->offset_to_coord, directory->offset, | ||
| 12914 | &offset)) | ||
| 12915 | goto bail; | ||
| 12916 | |||
| 12917 | if (lseek (fd, offset, SEEK_SET) != offset) | ||
| 12918 | goto bail; | ||
| 12919 | |||
| 12920 | if (read (fd, gvar->global_coords, coordinate_size) | ||
| 12921 | != coordinate_size) | ||
| 12922 | goto bail; | ||
| 12923 | |||
| 12924 | for (i = 0; i <= coordinate_size / sizeof *gvar->global_coords; ++i) | ||
| 12925 | sfnt_swap16 (&gvar->global_coords[i]); | ||
| 12926 | } | ||
| 12927 | |||
| 12928 | /* Finally, read the rest of the glyph variation data. */ | ||
| 12929 | gvar->data_size = data_size; | ||
| 12930 | gvar->glyph_variation_data | ||
| 12931 | = (unsigned char *) (gvar->global_coords | ||
| 12932 | + (coordinate_size | ||
| 12933 | / sizeof *gvar->global_coords)); | ||
| 12934 | |||
| 12935 | if (gvar->data_size) | ||
| 12936 | { | ||
| 12937 | if (INT_ADD_WRAPV (gvar->offset_to_data, directory->offset, | ||
| 12938 | &offset)) | ||
| 12939 | goto bail; | ||
| 12940 | |||
| 12941 | if (lseek (fd, offset, SEEK_SET) != offset) | ||
| 12942 | goto bail; | ||
| 12943 | |||
| 12944 | if (read (fd, gvar->glyph_variation_data, | ||
| 12945 | gvar->data_size) != gvar->data_size) | ||
| 12946 | goto bail; | ||
| 12947 | } | ||
| 12948 | |||
| 12949 | /* Return the read gvar table. */ | ||
| 12950 | return gvar; | ||
| 12951 | |||
| 12952 | bail: | ||
| 12953 | xfree (gvar); | ||
| 12954 | return NULL; | ||
| 12955 | } | ||
| 12956 | |||
| 12957 | |||
| 12958 | |||
| 12959 | /* Structure repesenting a set of axis coordinates and their | ||
| 12960 | normalized equivalents. | ||
| 12961 | |||
| 12962 | To use this structure, call | ||
| 12963 | |||
| 12964 | sfnt_init_blend (&blend, fvar, gvar) | ||
| 12965 | |||
| 12966 | on a `struct sfnt_blend *', with an appropriate fvar and gvar | ||
| 12967 | table. | ||
| 12968 | |||
| 12969 | Then, fill in blend.coords with the un-normalized coordinates, | ||
| 12970 | and call | ||
| 12971 | |||
| 12972 | sfnt_normalize_blend (&blend) | ||
| 12973 | |||
| 12974 | finally, call sfnt_vary_glyph and related functions. */ | ||
| 12975 | |||
| 12976 | struct sfnt_blend | ||
| 12977 | { | ||
| 12978 | /* The fvar table. This determines the number of elements in each | ||
| 12979 | of the arrays below. */ | ||
| 12980 | struct sfnt_fvar_table *fvar; | ||
| 12981 | |||
| 12982 | /* The gvar table. This provides the glyph variation data. */ | ||
| 12983 | struct sfnt_gvar_table *gvar; | ||
| 12984 | |||
| 12985 | /* Un-normalized coordinates. */ | ||
| 12986 | sfnt_fixed *coords; | ||
| 12987 | |||
| 12988 | /* Normalized coordinates. */ | ||
| 12989 | sfnt_fixed *norm_coords; | ||
| 12990 | }; | ||
| 12991 | |||
| 12992 | /* Initialize the specified BLEND with the given FVAR and GVAR | ||
| 12993 | tables. */ | ||
| 12994 | |||
| 12995 | static void | ||
| 12996 | sfnt_init_blend (struct sfnt_blend *blend, struct sfnt_fvar_table *fvar, | ||
| 12997 | struct sfnt_gvar_table *gvar) | ||
| 12998 | { | ||
| 12999 | size_t size; | ||
| 13000 | |||
| 13001 | blend->fvar = fvar; | ||
| 13002 | blend->gvar = gvar; | ||
| 13003 | |||
| 13004 | /* Allocate a single array to hold both coords and norm_coords. */ | ||
| 13005 | size = (fvar->axis_count * sizeof *blend->coords * 2); | ||
| 13006 | blend->coords = xmalloc (size); | ||
| 13007 | blend->norm_coords = blend->coords + fvar->axis_count; | ||
| 13008 | } | ||
| 13009 | |||
| 13010 | /* Free what was initialized in the specified BLEND. */ | ||
| 13011 | |||
| 13012 | static void | ||
| 13013 | sfnt_free_blend (struct sfnt_blend *blend) | ||
| 13014 | { | ||
| 13015 | xfree (blend->coords); | ||
| 13016 | } | ||
| 13017 | |||
| 13018 | /* Normalize BLEND->fvar->axis_count coordinates in BLEND->coords and | ||
| 13019 | place the result in BLEND->norm_coords. */ | ||
| 13020 | |||
| 13021 | static void | ||
| 13022 | sfnt_normalize_blend (struct sfnt_blend *blend) | ||
| 13023 | { | ||
| 13024 | struct sfnt_variation_axis *axis; | ||
| 13025 | int i; | ||
| 13026 | sfnt_fixed coord; | ||
| 13027 | |||
| 13028 | /* For each axis... */ | ||
| 13029 | for (i = 0; i < blend->fvar->axis_count; ++i) | ||
| 13030 | { | ||
| 13031 | /* Normalize based on [min, default, max], into [-1, 0, 1]. */ | ||
| 13032 | axis = &blend->fvar->axis[i]; | ||
| 13033 | |||
| 13034 | /* Load the current design coordinate. */ | ||
| 13035 | coord = blend->coords[i]; | ||
| 13036 | |||
| 13037 | /* Keep it within bounds. */ | ||
| 13038 | |||
| 13039 | if (coord > axis->max_value) | ||
| 13040 | coord = axis->max_value; | ||
| 13041 | else if (coord < axis->min_value) | ||
| 13042 | coord = axis->min_value; | ||
| 13043 | |||
| 13044 | if (coord > axis->default_value) | ||
| 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 | { | ||
| 13057 | if (axis->default_value != axis->min_value) | ||
| 13058 | blend->norm_coords[i] | ||
| 13059 | = sfnt_div_fixed (sfnt_sub (coord, axis->default_value), | ||
| 13060 | sfnt_sub (axis->default_value, | ||
| 13061 | axis->min_value)); | ||
| 13062 | else | ||
| 13063 | blend->norm_coords[i] = 0; | ||
| 13064 | } | ||
| 13065 | else | ||
| 13066 | blend->norm_coords[i] = 0; | ||
| 13067 | } | ||
| 13068 | |||
| 13069 | /* TODO: process avar tables. */ | ||
| 13070 | } | ||
| 13071 | |||
| 13072 | |||
| 13073 | |||
| 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 | ||
| 13114 | number of points read in *NPOINTS_RETURN and the array of unpacked | ||
| 13115 | points, or NULL upon failure. | ||
| 13116 | |||
| 13117 | If non-NULL, set LOCATION to DATA plus the number of bytes read | ||
| 13118 | upon success. | ||
| 13119 | |||
| 13120 | Return (uint16_t *) -1 if there are no points at all. | ||
| 13121 | In this case, deltas will apply to all points in the glyph, | ||
| 13122 | and *NPOINTS_RETURN will be UINT16_MAX. | ||
| 13123 | |||
| 13124 | END is one byte past the last byte in DATA. */ | ||
| 13125 | |||
| 13126 | static uint16_t * | ||
| 13127 | sfnt_read_packed_points (unsigned char *restrict data, | ||
| 13128 | uint16_t *npoints_return, | ||
| 13129 | unsigned char *restrict end, | ||
| 13130 | unsigned char *restrict *location) | ||
| 13131 | { | ||
| 13132 | int npoints; | ||
| 13133 | uint16_t *points; | ||
| 13134 | int i, first, control; | ||
| 13135 | |||
| 13136 | points = NULL; | ||
| 13137 | npoints = 0; | ||
| 13138 | |||
| 13139 | if (data >= end) | ||
| 13140 | return NULL; | ||
| 13141 | |||
| 13142 | /* Load the control byte. */ | ||
| 13143 | control = *data++; | ||
| 13144 | |||
| 13145 | if (!control) | ||
| 13146 | { | ||
| 13147 | *npoints_return = UINT16_MAX; | ||
| 13148 | *location = data; | ||
| 13149 | return (uint16_t *) -1; | ||
| 13150 | } | ||
| 13151 | |||
| 13152 | /* Now figure out the number of points within. */ | ||
| 13153 | |||
| 13154 | if (control & 0x80) | ||
| 13155 | { | ||
| 13156 | npoints = control & 0x7f; | ||
| 13157 | npoints <<= 8; | ||
| 13158 | |||
| 13159 | if (data >= end) | ||
| 13160 | return NULL; | ||
| 13161 | |||
| 13162 | npoints |= *data++; | ||
| 13163 | } | ||
| 13164 | else | ||
| 13165 | npoints = control; | ||
| 13166 | |||
| 13167 | /* Start reading points. */ | ||
| 13168 | first = 0; | ||
| 13169 | i = 0; | ||
| 13170 | points = xmalloc (sizeof *points * npoints); | ||
| 13171 | |||
| 13172 | while (i < npoints) | ||
| 13173 | { | ||
| 13174 | if (data >= end) | ||
| 13175 | goto bail; | ||
| 13176 | |||
| 13177 | control = *data++; | ||
| 13178 | |||
| 13179 | if (control & 0x80) | ||
| 13180 | { | ||
| 13181 | /* Next control & 0x7f words are points. */ | ||
| 13182 | |||
| 13183 | control &= 0x7f; | ||
| 13184 | |||
| 13185 | while (control != -1 && i < npoints) | ||
| 13186 | { | ||
| 13187 | if (data >= end || data + 1 >= end) | ||
| 13188 | goto bail; | ||
| 13189 | |||
| 13190 | first += *data++ << 8u; | ||
| 13191 | first += *data++; | ||
| 13192 | points[i] = first; | ||
| 13193 | control -= 1, ++i; | ||
| 13194 | } | ||
| 13195 | } | ||
| 13196 | else | ||
| 13197 | { | ||
| 13198 | /* Next control bytes are points. */ | ||
| 13199 | |||
| 13200 | while (control != -1 && i < npoints) | ||
| 13201 | { | ||
| 13202 | if (data >= end) | ||
| 13203 | goto bail; | ||
| 13204 | |||
| 13205 | first += *data++; | ||
| 13206 | points[i] = first; | ||
| 13207 | control -= 1, ++i; | ||
| 13208 | } | ||
| 13209 | } | ||
| 13210 | } | ||
| 13211 | |||
| 13212 | /* Return the points read. */ | ||
| 13213 | *npoints_return = npoints; | ||
| 13214 | *location = data; | ||
| 13215 | return points; | ||
| 13216 | |||
| 13217 | bail: | ||
| 13218 | xfree (points); | ||
| 13219 | return NULL; | ||
| 13220 | } | ||
| 13221 | |||
| 13222 | /* Read and return N packed deltas from DATA. Set *DATA_RETURN to | ||
| 13223 | DATA plus the number of bytes read. | ||
| 13224 | |||
| 13225 | END is the end of the glyph variation data. Value is an array of N | ||
| 13226 | deltas upon success, and NULL upon failure. */ | ||
| 13227 | |||
| 13228 | static sfnt_fword * | ||
| 13229 | sfnt_read_packed_deltas (unsigned char *restrict data, | ||
| 13230 | unsigned char *restrict end, | ||
| 13231 | int n, | ||
| 13232 | unsigned char *restrict *data_return) | ||
| 13233 | { | ||
| 13234 | sfnt_fword *deltas; | ||
| 13235 | int i, count; | ||
| 13236 | unsigned char control; | ||
| 13237 | |||
| 13238 | if (data >= end) | ||
| 13239 | return NULL; | ||
| 13240 | |||
| 13241 | deltas = xmalloc (sizeof *deltas * n); | ||
| 13242 | i = 0; | ||
| 13243 | |||
| 13244 | while (i < n) | ||
| 13245 | { | ||
| 13246 | if (data >= end) | ||
| 13247 | goto fail; | ||
| 13248 | |||
| 13249 | control = *data++; | ||
| 13250 | count = control & 0x3f; | ||
| 13251 | |||
| 13252 | while (count != -1 && i < n) | ||
| 13253 | { | ||
| 13254 | if (control & 0x80) | ||
| 13255 | deltas[i++] = 0; | ||
| 13256 | else if (control & 0x40) | ||
| 13257 | { | ||
| 13258 | if (data + 1 >= end) | ||
| 13259 | goto fail; | ||
| 13260 | |||
| 13261 | deltas[i] = (signed char) *data++; | ||
| 13262 | deltas[i] *= 65536; | ||
| 13263 | deltas[i++] |= *data++; | ||
| 13264 | } | ||
| 13265 | else | ||
| 13266 | { | ||
| 13267 | if (data >= end) | ||
| 13268 | goto fail; | ||
| 13269 | |||
| 13270 | deltas[i++] = (signed char) *data++; | ||
| 13271 | } | ||
| 13272 | |||
| 13273 | --count; | ||
| 13274 | } | ||
| 13275 | } | ||
| 13276 | |||
| 13277 | *data_return = data; | ||
| 13278 | return deltas; | ||
| 13279 | |||
| 13280 | fail: | ||
| 13281 | xfree (deltas); | ||
| 13282 | return NULL; | ||
| 13283 | } | ||
| 13284 | |||
| 13285 | /* Given a BLEND containing normalized coordinates, an array of | ||
| 13286 | BLEND->gvar->axis_count tuple coordinates, and, if INTERMEDIATE_P, | ||
| 13287 | a range of tuple coordinates from INTERMEDIATE_START to | ||
| 13288 | INTERMEDIATE_END, return the scaling factor to apply to deltas for | ||
| 13289 | each corresponding point. */ | ||
| 13290 | |||
| 13291 | static sfnt_fixed | ||
| 13292 | sfnt_compute_tuple_scale (struct sfnt_blend *blend, bool intermediate_p, | ||
| 13293 | sfnt_f2dot14 *coords, | ||
| 13294 | sfnt_f2dot14 *intermediate_start, | ||
| 13295 | sfnt_f2dot14 *intermediate_end) | ||
| 13296 | { | ||
| 13297 | int i; | ||
| 13298 | sfnt_fixed coord, start, end; | ||
| 13299 | sfnt_fixed scale; | ||
| 13300 | |||
| 13301 | /* scale is initially 1.0. */ | ||
| 13302 | scale = 0200000; | ||
| 13303 | |||
| 13304 | for (i = 0; i < blend->gvar->axis_count; ++i) | ||
| 13305 | { | ||
| 13306 | /* Load values for this axis, scaled up to sfnt_fixed. */ | ||
| 13307 | coord = coords[i] * 4; | ||
| 13308 | |||
| 13309 | if (intermediate_p) | ||
| 13310 | { | ||
| 13311 | start = intermediate_start[i] * 4; | ||
| 13312 | end = intermediate_start[i] * 4; | ||
| 13313 | } | ||
| 13314 | |||
| 13315 | /* Ignore tuples that can be skipped. */ | ||
| 13316 | |||
| 13317 | if (!coord) | ||
| 13318 | continue; | ||
| 13319 | |||
| 13320 | /* If the coordinate is set to 0, then deltas should not be | ||
| 13321 | applied. Return 0. */ | ||
| 13322 | |||
| 13323 | if (!blend->norm_coords[i]) | ||
| 13324 | return 0; | ||
| 13325 | |||
| 13326 | /* If no scaling need take place, continue. */ | ||
| 13327 | |||
| 13328 | if (blend->norm_coords[i] == coord) | ||
| 13329 | continue; | ||
| 13330 | |||
| 13331 | if (!intermediate_p) | ||
| 13332 | { | ||
| 13333 | /* Not an intermediate tuple; if coord is less than 0 and | ||
| 13334 | blend->norm_coords[i] < coord, or coord is more than 0 | ||
| 13335 | and blend->norm_coords[i] > coord, then it doesn't fit, | ||
| 13336 | so return. */ | ||
| 13337 | |||
| 13338 | if (blend->norm_coords[i] < MIN (0, coord) | ||
| 13339 | || blend->norm_coords[i] > MAX (0, coord)) | ||
| 13340 | return 0; | ||
| 13341 | |||
| 13342 | scale = sfnt_multiply_divide_signed (scale, | ||
| 13343 | blend->norm_coords[i], | ||
| 13344 | coord); | ||
| 13345 | } | ||
| 13346 | else | ||
| 13347 | { | ||
| 13348 | /* Otherwise, renormalize between start and end. */ | ||
| 13349 | |||
| 13350 | if (blend->norm_coords[i] < start | ||
| 13351 | || blend->norm_coords[i] > end) | ||
| 13352 | return 0; | ||
| 13353 | |||
| 13354 | if (blend->norm_coords[i] < coord) | ||
| 13355 | scale = sfnt_multiply_divide (scale, | ||
| 13356 | blend->norm_coords[i] - start, | ||
| 13357 | coord - start); | ||
| 13358 | else | ||
| 13359 | scale = sfnt_multiply_divide (scale, | ||
| 13360 | end - blend->norm_coords[i], | ||
| 13361 | end - coord); | ||
| 13362 | } | ||
| 13363 | } | ||
| 13364 | |||
| 13365 | return scale; | ||
| 13366 | } | ||
| 13367 | |||
| 13368 | /* Infer point positions for points that have been partially moved | ||
| 13369 | within the contour in GLYPH denoted by START and END. */ | ||
| 13370 | |||
| 13371 | static void | ||
| 13372 | sfnt_infer_deltas_1 (struct sfnt_glyph *glyph, size_t start, | ||
| 13373 | size_t end, bool *touched, sfnt_fword *x, | ||
| 13374 | sfnt_fword *y) | ||
| 13375 | { | ||
| 13376 | size_t i, pair_start, pair_end, pair_first, j; | ||
| 13377 | sfnt_fword min_pos, max_pos, position; | ||
| 13378 | sfnt_fixed ratio, delta; | ||
| 13379 | |||
| 13380 | pair_start = pair_first = -1; | ||
| 13381 | |||
| 13382 | /* Look for pairs of touched points. */ | ||
| 13383 | |||
| 13384 | for (i = start; i <= end; ++i) | ||
| 13385 | { | ||
| 13386 | if (!touched[i]) | ||
| 13387 | continue; | ||
| 13388 | |||
| 13389 | if (pair_start == -1) | ||
| 13390 | { | ||
| 13391 | pair_first = i; | ||
| 13392 | goto next; | ||
| 13393 | } | ||
| 13394 | |||
| 13395 | pair_end = i; | ||
| 13396 | |||
| 13397 | /* pair_start to pair_end are now a pair of points, where points | ||
| 13398 | in between should be interpolated. */ | ||
| 13399 | |||
| 13400 | for (j = pair_start + 1; j < pair_end; ++j) | ||
| 13401 | { | ||
| 13402 | /* Consider the X axis. Set min_pos and max_pos to the | ||
| 13403 | smallest and greatest values along that axis. */ | ||
| 13404 | min_pos = MIN (x[pair_start], x[pair_end]); | ||
| 13405 | max_pos = MAX (x[pair_start], x[pair_end]); | ||
| 13406 | |||
| 13407 | /* Now see if the current point lies between min and | ||
| 13408 | max... */ | ||
| 13409 | if (x[j] >= min_pos && x[j] <= max_pos) | ||
| 13410 | { | ||
| 13411 | /* If min_pos and max_pos are the same, apply | ||
| 13412 | pair_start's delta if it is identical to that of | ||
| 13413 | pair_end, or apply nothing at all otherwise. */ | ||
| 13414 | |||
| 13415 | if (min_pos == max_pos) | ||
| 13416 | { | ||
| 13417 | if ((glyph->simple->x_coordinates[pair_start] | ||
| 13418 | - x[pair_start]) | ||
| 13419 | == (glyph->simple->x_coordinates[pair_end] | ||
| 13420 | - x[pair_end])) | ||
| 13421 | glyph->simple->x_coordinates[j] | ||
| 13422 | += (glyph->simple->x_coordinates[pair_start] | ||
| 13423 | - x[pair_start]); | ||
| 13424 | |||
| 13425 | continue; | ||
| 13426 | } | ||
| 13427 | |||
| 13428 | /* Interpolate between min_pos and max_pos. */ | ||
| 13429 | ratio = sfnt_div_fixed ((sfnt_sub (x[j], min_pos) | ||
| 13430 | * 65536), | ||
| 13431 | (sfnt_sub (max_pos, min_pos) | ||
| 13432 | * 65536)); | ||
| 13433 | |||
| 13434 | /* Load the current positions of pair_start and pair_end | ||
| 13435 | along this axis. */ | ||
| 13436 | min_pos = MIN (glyph->simple->x_coordinates[pair_start], | ||
| 13437 | glyph->simple->x_coordinates[pair_end]); | ||
| 13438 | max_pos = MAX (glyph->simple->x_coordinates[pair_start], | ||
| 13439 | glyph->simple->x_coordinates[pair_end]); | ||
| 13440 | |||
| 13441 | /* Lerp in between. */ | ||
| 13442 | delta = sfnt_sub (max_pos, min_pos); | ||
| 13443 | delta = sfnt_mul_fixed (ratio, delta); | ||
| 13444 | glyph->simple->x_coordinates[j] = min_pos + delta; | ||
| 13445 | } | ||
| 13446 | else | ||
| 13447 | { | ||
| 13448 | /* ... otheriwse, move point j by the delta of the | ||
| 13449 | nearest touched point. */ | ||
| 13450 | |||
| 13451 | if (x[j] >= max_pos) | ||
| 13452 | { | ||
| 13453 | position = MAX (glyph->simple->x_coordinates[pair_start], | ||
| 13454 | glyph->simple->x_coordinates[pair_end]); | ||
| 13455 | delta = position - max_pos; | ||
| 13456 | } | ||
| 13457 | else | ||
| 13458 | { | ||
| 13459 | position = MIN (glyph->simple->x_coordinates[pair_start], | ||
| 13460 | glyph->simple->x_coordinates[pair_end]); | ||
| 13461 | delta = position - min_pos; | ||
| 13462 | } | ||
| 13463 | |||
| 13464 | glyph->simple->x_coordinates[j] = x[j] + delta; | ||
| 13465 | } | ||
| 13466 | |||
| 13467 | /* Now, consider the Y axis. */ | ||
| 13468 | min_pos = MIN (y[pair_start], y[pair_end]); | ||
| 13469 | max_pos = MAX (y[pair_start], y[pair_end]); | ||
| 13470 | |||
| 13471 | /* Now see if the current point lies between min and | ||
| 13472 | max... */ | ||
| 13473 | if (y[j] >= min_pos && y[j] <= max_pos) | ||
| 13474 | { | ||
| 13475 | /* If min_pos and max_pos are the same, apply | ||
| 13476 | pair_start's delta if it is identical to that of | ||
| 13477 | pair_end, or apply nothing at all otherwise. */ | ||
| 13478 | |||
| 13479 | if (min_pos == max_pos) | ||
| 13480 | { | ||
| 13481 | if ((glyph->simple->y_coordinates[pair_start] | ||
| 13482 | - y[pair_start]) | ||
| 13483 | == (glyph->simple->y_coordinates[pair_end] | ||
| 13484 | - y[pair_end])) | ||
| 13485 | glyph->simple->y_coordinates[j] | ||
| 13486 | += (glyph->simple->y_coordinates[pair_start] | ||
| 13487 | - y[pair_start]); | ||
| 13488 | |||
| 13489 | continue; | ||
| 13490 | } | ||
| 13491 | |||
| 13492 | /* Interpolate between min_pos and max_pos. */ | ||
| 13493 | ratio = sfnt_div_fixed ((sfnt_sub (y[j], min_pos) | ||
| 13494 | * 65536), | ||
| 13495 | (sfnt_sub (max_pos, min_pos) | ||
| 13496 | * 65536)); | ||
| 13497 | |||
| 13498 | /* Load the current positions of pair_start and pair_end | ||
| 13499 | along this axis. */ | ||
| 13500 | min_pos = MIN (glyph->simple->y_coordinates[pair_start], | ||
| 13501 | glyph->simple->y_coordinates[pair_end]); | ||
| 13502 | max_pos = MAX (glyph->simple->y_coordinates[pair_start], | ||
| 13503 | glyph->simple->y_coordinates[pair_end]); | ||
| 13504 | |||
| 13505 | /* Lerp in between. */ | ||
| 13506 | delta = sfnt_sub (max_pos, min_pos); | ||
| 13507 | delta = sfnt_mul_fixed (ratio, delta); | ||
| 13508 | glyph->simple->y_coordinates[j] = min_pos + delta; | ||
| 13509 | } | ||
| 13510 | else | ||
| 13511 | { | ||
| 13512 | /* ... otheriwse, move point j by the delta of the | ||
| 13513 | nearest touched point. */ | ||
| 13514 | |||
| 13515 | if (y[j] >= max_pos) | ||
| 13516 | { | ||
| 13517 | position = MAX (glyph->simple->y_coordinates[pair_start], | ||
| 13518 | glyph->simple->y_coordinates[pair_end]); | ||
| 13519 | delta = position - max_pos; | ||
| 13520 | } | ||
| 13521 | else | ||
| 13522 | { | ||
| 13523 | position = MIN (glyph->simple->y_coordinates[pair_start], | ||
| 13524 | glyph->simple->y_coordinates[pair_end]); | ||
| 13525 | delta = position - min_pos; | ||
| 13526 | } | ||
| 13527 | |||
| 13528 | glyph->simple->y_coordinates[j] = y[j] + delta; | ||
| 13529 | } | ||
| 13530 | } | ||
| 13531 | |||
| 13532 | next: | ||
| 13533 | pair_start = i; | ||
| 13534 | } | ||
| 13535 | |||
| 13536 | /* If pair_start is set, then lerp points between it and | ||
| 13537 | pair_first. */ | ||
| 13538 | |||
| 13539 | if (pair_start != (size_t) -1) | ||
| 13540 | { | ||
| 13541 | j = pair_start + 1; | ||
| 13542 | |||
| 13543 | if (j > end) | ||
| 13544 | j = start; | ||
| 13545 | |||
| 13546 | pair_end = pair_first; | ||
| 13547 | |||
| 13548 | while (j != pair_first) | ||
| 13549 | { | ||
| 13550 | /* Consider the X axis. Set min_pos and max_pos to the | ||
| 13551 | smallest and greatest values along that axis. */ | ||
| 13552 | min_pos = MIN (x[pair_start], x[pair_end]); | ||
| 13553 | max_pos = MAX (x[pair_start], x[pair_end]); | ||
| 13554 | |||
| 13555 | /* Now see if the current point lies between min and | ||
| 13556 | max... */ | ||
| 13557 | if (x[j] >= min_pos && x[j] <= max_pos) | ||
| 13558 | { | ||
| 13559 | /* If min_pos and max_pos are the same, apply | ||
| 13560 | pair_start's delta if it is identical to that of | ||
| 13561 | pair_end, or apply nothing at all otherwise. */ | ||
| 13562 | |||
| 13563 | if (min_pos == max_pos) | ||
| 13564 | { | ||
| 13565 | if ((glyph->simple->x_coordinates[pair_start] | ||
| 13566 | - x[pair_start]) | ||
| 13567 | == (glyph->simple->x_coordinates[pair_end] | ||
| 13568 | - x[pair_end])) | ||
| 13569 | glyph->simple->x_coordinates[j] | ||
| 13570 | += (glyph->simple->x_coordinates[pair_start] | ||
| 13571 | - x[pair_start]); | ||
| 13572 | |||
| 13573 | goto next_1; | ||
| 13574 | } | ||
| 13575 | |||
| 13576 | /* Interpolate between min_pos and max_pos. */ | ||
| 13577 | ratio = sfnt_div_fixed ((sfnt_sub (x[j], min_pos) | ||
| 13578 | * 65536), | ||
| 13579 | (sfnt_sub (max_pos, min_pos) | ||
| 13580 | * 65536)); | ||
| 13581 | |||
| 13582 | /* Load the current positions of pair_start and pair_end | ||
| 13583 | along this axis. */ | ||
| 13584 | min_pos = MIN (glyph->simple->x_coordinates[pair_start], | ||
| 13585 | glyph->simple->x_coordinates[pair_end]); | ||
| 13586 | max_pos = MAX (glyph->simple->x_coordinates[pair_start], | ||
| 13587 | glyph->simple->x_coordinates[pair_end]); | ||
| 13588 | |||
| 13589 | /* Lerp in between. */ | ||
| 13590 | delta = sfnt_sub (max_pos, min_pos); | ||
| 13591 | delta = sfnt_mul_fixed (ratio, delta); | ||
| 13592 | glyph->simple->x_coordinates[j] = min_pos + delta; | ||
| 13593 | } | ||
| 13594 | else | ||
| 13595 | { | ||
| 13596 | /* ... otheriwse, move point j by the delta of the | ||
| 13597 | nearest touched point. */ | ||
| 13598 | |||
| 13599 | if (x[j] >= max_pos) | ||
| 13600 | { | ||
| 13601 | position = MAX (glyph->simple->x_coordinates[pair_start], | ||
| 13602 | glyph->simple->x_coordinates[pair_end]); | ||
| 13603 | delta = position - max_pos; | ||
| 13604 | } | ||
| 13605 | else | ||
| 13606 | { | ||
| 13607 | position = MIN (glyph->simple->x_coordinates[pair_start], | ||
| 13608 | glyph->simple->x_coordinates[pair_end]); | ||
| 13609 | delta = position - min_pos; | ||
| 13610 | } | ||
| 13611 | |||
| 13612 | glyph->simple->x_coordinates[j] = x[j] + delta; | ||
| 13613 | } | ||
| 13614 | |||
| 13615 | /* Now, consider the Y axis. */ | ||
| 13616 | min_pos = MIN (y[pair_start], y[pair_end]); | ||
| 13617 | max_pos = MAX (y[pair_start], y[pair_end]); | ||
| 13618 | |||
| 13619 | /* Now see if the current point lies between min and | ||
| 13620 | max... */ | ||
| 13621 | if (y[j] >= min_pos && y[j] <= max_pos) | ||
| 13622 | { | ||
| 13623 | /* If min_pos and max_pos are the same, apply | ||
| 13624 | pair_start's delta if it is identical to that of | ||
| 13625 | pair_end, or apply nothing at all otherwise. */ | ||
| 13626 | |||
| 13627 | if (min_pos == max_pos) | ||
| 13628 | { | ||
| 13629 | if ((glyph->simple->y_coordinates[pair_start] | ||
| 13630 | - y[pair_start]) | ||
| 13631 | == (glyph->simple->y_coordinates[pair_end] | ||
| 13632 | - y[pair_end])) | ||
| 13633 | glyph->simple->y_coordinates[j] | ||
| 13634 | += (glyph->simple->y_coordinates[pair_start] | ||
| 13635 | - y[pair_start]); | ||
| 13636 | |||
| 13637 | goto next_1; | ||
| 13638 | } | ||
| 13639 | |||
| 13640 | /* Interpolate between min_pos and max_pos. */ | ||
| 13641 | ratio = sfnt_div_fixed ((sfnt_sub (y[j], min_pos) | ||
| 13642 | * 65536), | ||
| 13643 | (sfnt_sub (max_pos, min_pos) | ||
| 13644 | * 65536)); | ||
| 13645 | |||
| 13646 | /* Load the current positions of pair_start and pair_end | ||
| 13647 | along this axis. */ | ||
| 13648 | min_pos = MIN (glyph->simple->y_coordinates[pair_start], | ||
| 13649 | glyph->simple->y_coordinates[pair_end]); | ||
| 13650 | max_pos = MAX (glyph->simple->y_coordinates[pair_start], | ||
| 13651 | glyph->simple->y_coordinates[pair_end]); | ||
| 13652 | |||
| 13653 | /* Lerp in between. */ | ||
| 13654 | delta = sfnt_sub (max_pos, min_pos); | ||
| 13655 | delta = sfnt_mul_fixed (ratio, delta); | ||
| 13656 | glyph->simple->y_coordinates[j] = min_pos + delta; | ||
| 13657 | } | ||
| 13658 | else | ||
| 13659 | { | ||
| 13660 | /* ... otheriwse, move point j by the delta of the | ||
| 13661 | nearest touched point. */ | ||
| 13662 | |||
| 13663 | if (y[j] >= max_pos) | ||
| 13664 | { | ||
| 13665 | position = MAX (glyph->simple->y_coordinates[pair_start], | ||
| 13666 | glyph->simple->y_coordinates[pair_end]); | ||
| 13667 | delta = position - max_pos; | ||
| 13668 | } | ||
| 13669 | else | ||
| 13670 | { | ||
| 13671 | position = MIN (glyph->simple->y_coordinates[pair_start], | ||
| 13672 | glyph->simple->y_coordinates[pair_end]); | ||
| 13673 | delta = position - min_pos; | ||
| 13674 | } | ||
| 13675 | |||
| 13676 | glyph->simple->y_coordinates[j] = y[j] + delta; | ||
| 13677 | } | ||
| 13678 | |||
| 13679 | next_1: | ||
| 13680 | j++; | ||
| 13681 | if (j > end) | ||
| 13682 | j = start; | ||
| 13683 | } | ||
| 13684 | } | ||
| 13685 | } | ||
| 13686 | |||
| 13687 | /* Infer point positions for contours that have been partially moved | ||
| 13688 | by variation. For each contour in GLYPH, find pairs of points | ||
| 13689 | which have had deltas applied. For each such pair, interpolate | ||
| 13690 | points between the first point in the pair and the second by | ||
| 13691 | considering each point along every one of the two axes (X and Y) | ||
| 13692 | like so: | ||
| 13693 | |||
| 13694 | - For each point that lies between the first point and the last | ||
| 13695 | on the axis currently being considered, interpolate its | ||
| 13696 | position in that axis so that the ratio between the first | ||
| 13697 | point and the last in the original outline still holds. | ||
| 13698 | |||
| 13699 | - For each point that lies to the left or top of the first point | ||
| 13700 | on the axis being considered, use the delta of the first point. | ||
| 13701 | |||
| 13702 | - And finally, for each point that lies to the right or bottom of | ||
| 13703 | the last point on that axis, use the delta of the last | ||
| 13704 | point. | ||
| 13705 | |||
| 13706 | X and Y contain the original positions positions of each point. | ||
| 13707 | TOUCHED contains whether or not each point has been changed by | ||
| 13708 | an explicitly specified delta. | ||
| 13709 | |||
| 13710 | Apply the inferred deltas back to GLYPH. */ | ||
| 13711 | |||
| 13712 | static void | ||
| 13713 | sfnt_infer_deltas (struct sfnt_glyph *glyph, bool *touched, | ||
| 13714 | sfnt_fword *x, sfnt_fword *y) | ||
| 13715 | { | ||
| 13716 | size_t i; | ||
| 13717 | int point, first, end; | ||
| 13718 | |||
| 13719 | point = 0; | ||
| 13720 | for (i = 0; i < glyph->number_of_contours; ++i) | ||
| 13721 | { | ||
| 13722 | first = point; | ||
| 13723 | end = glyph->simple->end_pts_of_contours[i]; | ||
| 13724 | |||
| 13725 | /* Return if the glyph is invalid. */ | ||
| 13726 | |||
| 13727 | if (first >= glyph->simple->number_of_points | ||
| 13728 | || end >= glyph->simple->number_of_points | ||
| 13729 | || first > end) | ||
| 13730 | return; | ||
| 13731 | |||
| 13732 | sfnt_infer_deltas_1 (glyph, first, end, touched, x, y); | ||
| 13733 | point = end + 1; | ||
| 13734 | } | ||
| 13735 | } | ||
| 13736 | |||
| 13737 | /* Read the glyph variation data for the specified glyph ID from | ||
| 13738 | BLEND's gvar table. Apply the offsets to each point in the | ||
| 13739 | specified simple GLYPH, based on the specified BLEND. | ||
| 13740 | |||
| 13741 | Value is 0 upon success, else 1. | ||
| 13742 | |||
| 13743 | The glyph variation data consists of a number of elements, each of | ||
| 13744 | which has its own associated point numbers and deltas, and a list | ||
| 13745 | of one or two coordinates for each axis. Each such list is | ||
| 13746 | referred to as a ``tuple''. | ||
| 13747 | |||
| 13748 | The deltas, one for each point, are multipled by the normalized | ||
| 13749 | value of each axis and applied to those points for each tuple that | ||
| 13750 | is found to be applicable. | ||
| 13751 | |||
| 13752 | Each element of the glyph variation data is applicable to an axis | ||
| 13753 | if its list of coordinates: | ||
| 13754 | |||
| 13755 | - contains one element for each axis, and its axis has a value | ||
| 13756 | between 0 and that element. | ||
| 13757 | |||
| 13758 | - contains two elements for each axis, and its axis has a value | ||
| 13759 | between the first element and the second. | ||
| 13760 | |||
| 13761 | After the deltas are applied, any points without deltas must be | ||
| 13762 | interpolated similar to an IUP instruction. In addition, deltas | ||
| 13763 | may also be applied to phantom points within a glyph. */ | ||
| 13764 | |||
| 13765 | static int | ||
| 13766 | sfnt_vary_glyph (struct sfnt_blend *blend, sfnt_glyph id, | ||
| 13767 | struct sfnt_glyph *glyph) | ||
| 13768 | { | ||
| 13769 | uint32_t offset; | ||
| 13770 | struct sfnt_gvar_glyph_header header; | ||
| 13771 | uint16_t *points, npoints; | ||
| 13772 | int i, ntuples, j, point_count; | ||
| 13773 | unsigned char *tuple, *end, *data; | ||
| 13774 | uint16_t data_size, index, *glyph_points; | ||
| 13775 | sfnt_f2dot14 *restrict coords; | ||
| 13776 | sfnt_f2dot14 *restrict intermediate_start; | ||
| 13777 | sfnt_f2dot14 *restrict intermediate_end; | ||
| 13778 | sfnt_fword *dx, *dy, fword; | ||
| 13779 | struct sfnt_gvar_table *gvar; | ||
| 13780 | uint16_t *local_points, n_local_points; | ||
| 13781 | sfnt_fixed scale; | ||
| 13782 | ptrdiff_t data_offset; | ||
| 13783 | bool *touched; | ||
| 13784 | sfnt_fword *restrict original_x, *restrict original_y; | ||
| 13785 | |||
| 13786 | gvar = blend->gvar; | ||
| 13787 | |||
| 13788 | if (gvar->axis_count != blend->fvar->axis_count) | ||
| 13789 | return 1; | ||
| 13790 | |||
| 13791 | if (gvar->glyph_count <= id) | ||
| 13792 | return 1; | ||
| 13793 | |||
| 13794 | if (gvar->flags & 1) | ||
| 13795 | offset = gvar->u.offset_long[id]; | ||
| 13796 | else | ||
| 13797 | offset = gvar->u.offset_word[id] * 2u; | ||
| 13798 | |||
| 13799 | if (offset >= gvar->data_size) | ||
| 13800 | return 1; | ||
| 13801 | |||
| 13802 | end = gvar->glyph_variation_data + gvar->data_size; | ||
| 13803 | |||
| 13804 | /* Start reading the header. */ | ||
| 13805 | |||
| 13806 | if (offset + sizeof header > gvar->data_size) | ||
| 13807 | return 1; | ||
| 13808 | |||
| 13809 | memcpy (&header, gvar->glyph_variation_data + offset, | ||
| 13810 | sizeof header); | ||
| 13811 | |||
| 13812 | /* Swap the header. */ | ||
| 13813 | sfnt_swap16 (&header.tuple_count); | ||
| 13814 | sfnt_swap16 (&header.data_offset); | ||
| 13815 | |||
| 13816 | /* Prepare to read each tuple. */ | ||
| 13817 | ntuples = header.tuple_count & 0x0fff; | ||
| 13818 | |||
| 13819 | /* Initialize the data offset. This is incremented with each tuple | ||
| 13820 | read. */ | ||
| 13821 | data_offset = header.data_offset; | ||
| 13822 | |||
| 13823 | /* If gvar->flags & tuples_share_point_numbers, read the shared | ||
| 13824 | point numbers. */ | ||
| 13825 | |||
| 13826 | npoints = 0; | ||
| 13827 | |||
| 13828 | if (header.tuple_count & 0x8000) | ||
| 13829 | { | ||
| 13830 | data = gvar->glyph_variation_data + offset + data_offset; | ||
| 13831 | points = sfnt_read_packed_points (data, &npoints, end, | ||
| 13832 | &tuple); | ||
| 13833 | |||
| 13834 | if (!points) | ||
| 13835 | return 1; | ||
| 13836 | |||
| 13837 | /* Shared point numbers are part of the data after the tuple | ||
| 13838 | array. Thus, increment data_offset by tuple - data. `tuple' | ||
| 13839 | here holds no relation to a pointer to the current part of | ||
| 13840 | the tuple array that is being read later on. */ | ||
| 13841 | data_offset += tuple - data; | ||
| 13842 | } | ||
| 13843 | else | ||
| 13844 | points = NULL; | ||
| 13845 | |||
| 13846 | /* Start reading each tuple. */ | ||
| 13847 | tuple = gvar->glyph_variation_data + offset + sizeof header; | ||
| 13848 | |||
| 13849 | coords = xmalloc (gvar->axis_count * sizeof *coords * 3); | ||
| 13850 | intermediate_start = coords + gvar->axis_count; | ||
| 13851 | intermediate_end = coords + gvar->axis_count; | ||
| 13852 | |||
| 13853 | /* Allocate arrays of booleans and fwords to keep track of which | ||
| 13854 | points have been touched. */ | ||
| 13855 | touched = NULL; | ||
| 13856 | original_x = NULL; | ||
| 13857 | original_y = NULL; | ||
| 13858 | |||
| 13859 | for (i = 0; i < ntuples; ++i) | ||
| 13860 | { | ||
| 13861 | data = gvar->glyph_variation_data + offset + data_offset; | ||
| 13862 | |||
| 13863 | if (tuple + 3 >= end) | ||
| 13864 | goto fail1; | ||
| 13865 | |||
| 13866 | memcpy (&data_size, tuple, sizeof data_size); | ||
| 13867 | tuple += sizeof data_size; | ||
| 13868 | memcpy (&index, tuple, sizeof index); | ||
| 13869 | tuple += sizeof index; | ||
| 13870 | sfnt_swap16 (&data_size); | ||
| 13871 | sfnt_swap16 (&index); | ||
| 13872 | |||
| 13873 | /* Increment the offset to the data by the data size specified | ||
| 13874 | here. */ | ||
| 13875 | data_offset += data_size; | ||
| 13876 | |||
| 13877 | if (index & 0x8000) | ||
| 13878 | { | ||
| 13879 | /* Embedded coordinates are present. Read each | ||
| 13880 | coordinate and add it to the tuple. */ | ||
| 13881 | for (j = 0; j < gvar->axis_count; ++j) | ||
| 13882 | { | ||
| 13883 | if (tuple + 1 >= end) | ||
| 13884 | goto fail1; | ||
| 13885 | |||
| 13886 | memcpy (&coords[j], tuple, sizeof *coords); | ||
| 13887 | tuple += sizeof *coords; | ||
| 13888 | sfnt_swap16 (&coords[j]); | ||
| 13889 | } | ||
| 13890 | } | ||
| 13891 | else if ((index & 0xfff) > gvar->shared_coord_count) | ||
| 13892 | /* index exceeds the number of shared tuples present. */ | ||
| 13893 | goto fail1; | ||
| 13894 | else | ||
| 13895 | /* index points into gvar->axis_count coordinates making up | ||
| 13896 | the tuple. */ | ||
| 13897 | memcpy (coords, (gvar->global_coords | ||
| 13898 | + ((index & 0xfff) * gvar->axis_count)), | ||
| 13899 | gvar->axis_count * sizeof *coords); | ||
| 13900 | |||
| 13901 | /* Now read indeterminate tuples if required. */ | ||
| 13902 | if (index & 0x1000) | ||
| 13903 | { | ||
| 13904 | for (j = 0; j < gvar->axis_count; ++j) | ||
| 13905 | { | ||
| 13906 | if (tuple + 1 >= end) | ||
| 13907 | goto fail1; | ||
| 13908 | |||
| 13909 | memcpy (&intermediate_start[j], tuple, | ||
| 13910 | sizeof *intermediate_start); | ||
| 13911 | tuple += sizeof *intermediate_start; | ||
| 13912 | sfnt_swap16 (&intermediate_start[j]); | ||
| 13913 | } | ||
| 13914 | |||
| 13915 | for (j = 0; j < gvar->axis_count; ++j) | ||
| 13916 | { | ||
| 13917 | if (tuple + 1 >= end) | ||
| 13918 | goto fail1; | ||
| 13919 | |||
| 13920 | memcpy (&intermediate_end[j], tuple, | ||
| 13921 | sizeof *intermediate_end); | ||
| 13922 | tuple += sizeof *intermediate_end; | ||
| 13923 | sfnt_swap16 (&intermediate_end[j]); | ||
| 13924 | } | ||
| 13925 | } | ||
| 13926 | |||
| 13927 | /* See whether or not the tuple applies to the current variation | ||
| 13928 | configuration, and how much to scale them by. */ | ||
| 13929 | |||
| 13930 | scale = sfnt_compute_tuple_scale (blend, index & 0x1000, | ||
| 13931 | coords, intermediate_start, | ||
| 13932 | intermediate_end); | ||
| 13933 | |||
| 13934 | if (!scale) | ||
| 13935 | continue; | ||
| 13936 | |||
| 13937 | local_points = NULL; | ||
| 13938 | |||
| 13939 | /* Finally, read private point numbers. | ||
| 13940 | Set local_points to those numbers; it will be freed | ||
| 13941 | once the loop ends. */ | ||
| 13942 | |||
| 13943 | if (index & 0x2000) | ||
| 13944 | { | ||
| 13945 | local_points = sfnt_read_packed_points (data, &n_local_points, | ||
| 13946 | end, &data); | ||
| 13947 | if (!local_points) | ||
| 13948 | goto fail1; | ||
| 13949 | |||
| 13950 | point_count = n_local_points; | ||
| 13951 | glyph_points = local_points; | ||
| 13952 | } | ||
| 13953 | else | ||
| 13954 | { | ||
| 13955 | /* If there are no private point numbers, use global | ||
| 13956 | points. */ | ||
| 13957 | point_count = npoints; | ||
| 13958 | glyph_points = points; | ||
| 13959 | } | ||
| 13960 | |||
| 13961 | /* Now, read packed deltas. */ | ||
| 13962 | |||
| 13963 | dx = NULL; | ||
| 13964 | dy = NULL; | ||
| 13965 | |||
| 13966 | switch (point_count) | ||
| 13967 | { | ||
| 13968 | case UINT16_MAX: | ||
| 13969 | /* Deltas are provided for all points in the glyph. | ||
| 13970 | No glyph should have more than 65535 points. */ | ||
| 13971 | |||
| 13972 | if (glyph->simple->number_of_points > 65535) | ||
| 13973 | abort (); | ||
| 13974 | |||
| 13975 | /* Add 4 phantom points to each end. */ | ||
| 13976 | dx = sfnt_read_packed_deltas (data, end, | ||
| 13977 | glyph->simple->number_of_points + 4, | ||
| 13978 | &data); | ||
| 13979 | dy = sfnt_read_packed_deltas (data, end, | ||
| 13980 | glyph->simple->number_of_points + 4, | ||
| 13981 | &data); | ||
| 13982 | |||
| 13983 | if (!dx || !dy) | ||
| 13984 | goto fail3; | ||
| 13985 | |||
| 13986 | /* Apply each delta to the simple glyph. */ | ||
| 13987 | |||
| 13988 | for (i = 0; i < glyph->simple->number_of_points; ++i) | ||
| 13989 | { | ||
| 13990 | fword = sfnt_mul_fixed (dx[i], scale); | ||
| 13991 | glyph->simple->x_coordinates[i] += fword; | ||
| 13992 | fword = sfnt_mul_fixed (dy[i], scale); | ||
| 13993 | glyph->simple->y_coordinates[i] += fword; | ||
| 13994 | } | ||
| 13995 | |||
| 13996 | /* TODO: apply metrics variations. */ | ||
| 13997 | break; | ||
| 13998 | |||
| 13999 | default: | ||
| 14000 | dx = sfnt_read_packed_deltas (data, end, point_count, &data); | ||
| 14001 | dy = sfnt_read_packed_deltas (data, end, point_count, &data); | ||
| 14002 | |||
| 14003 | if (!dx || !dy) | ||
| 14004 | goto fail3; | ||
| 14005 | |||
| 14006 | /* Deltas are only applied for each point number read. */ | ||
| 14007 | |||
| 14008 | if (!original_x) | ||
| 14009 | { | ||
| 14010 | touched = xmalloc (sizeof *touched | ||
| 14011 | * glyph->simple->number_of_points); | ||
| 14012 | original_x = xmalloc (sizeof *original_x * 2 | ||
| 14013 | * glyph->simple->number_of_points); | ||
| 14014 | original_y = original_x + glyph->simple->number_of_points; | ||
| 14015 | memcpy (original_x, glyph->simple->x_coordinates, | ||
| 14016 | (sizeof *original_x | ||
| 14017 | * glyph->simple->number_of_points)); | ||
| 14018 | memcpy (original_y, glyph->simple->y_coordinates, | ||
| 14019 | (sizeof *original_y | ||
| 14020 | * glyph->simple->number_of_points)); | ||
| 14021 | } | ||
| 14022 | |||
| 14023 | memset (touched, 0, (sizeof *touched | ||
| 14024 | * glyph->simple->number_of_points)); | ||
| 14025 | |||
| 14026 | for (i = 0; i < point_count; ++i) | ||
| 14027 | { | ||
| 14028 | /* Make sure the point doesn't end up out of bounds. */ | ||
| 14029 | if (glyph_points[i] >= glyph->simple->number_of_points) | ||
| 14030 | continue; | ||
| 14031 | |||
| 14032 | fword = sfnt_mul_fixed (dx[i], scale); | ||
| 14033 | glyph->simple->x_coordinates[glyph_points[i]] += fword; | ||
| 14034 | fword = sfnt_mul_fixed (dy[i], scale); | ||
| 14035 | glyph->simple->y_coordinates[glyph_points[i]] += fword; | ||
| 14036 | touched[glyph_points[i]] = true; | ||
| 14037 | } | ||
| 14038 | |||
| 14039 | sfnt_infer_deltas (glyph, touched, original_x, | ||
| 14040 | original_y); | ||
| 14041 | |||
| 14042 | /* TODO: apply metrics variations. */ | ||
| 14043 | break; | ||
| 14044 | } | ||
| 14045 | |||
| 14046 | xfree (dx); | ||
| 14047 | xfree (dy); | ||
| 14048 | |||
| 14049 | if (local_points != (uint16_t *) -1) | ||
| 14050 | xfree (local_points); | ||
| 14051 | } | ||
| 14052 | |||
| 14053 | /* Return success. */ | ||
| 14054 | |||
| 14055 | xfree (touched); | ||
| 14056 | xfree (coords); | ||
| 14057 | xfree (original_x); | ||
| 14058 | |||
| 14059 | if (points != (uint16_t *) -1) | ||
| 14060 | xfree (points); | ||
| 14061 | |||
| 14062 | return 0; | ||
| 14063 | |||
| 14064 | fail3: | ||
| 14065 | xfree (dx); | ||
| 14066 | xfree (dy); | ||
| 14067 | xfree (local_points); | ||
| 14068 | fail1: | ||
| 14069 | xfree (touched); | ||
| 14070 | xfree (coords); | ||
| 14071 | xfree (original_x); | ||
| 14072 | |||
| 14073 | if (points != (uint16_t *) -1) | ||
| 14074 | xfree (points); | ||
| 14075 | |||
| 14076 | return 1; | ||
| 14077 | } | ||
| 14078 | |||
| 14079 | #endif /* TEST */ | ||
| 14080 | |||
| 12434 | 14081 | ||
| 12435 | 14082 | ||
| 12436 | #ifdef TEST | 14083 | #ifdef TEST |
| @@ -16262,15 +17909,22 @@ main (int argc, char **argv) | |||
| 16262 | struct sfnt_prep_table *prep; | 17909 | struct sfnt_prep_table *prep; |
| 16263 | struct sfnt_graphics_state state; | 17910 | struct sfnt_graphics_state state; |
| 16264 | struct sfnt_instructed_outline *value; | 17911 | struct sfnt_instructed_outline *value; |
| 17912 | struct sfnt_fvar_table *fvar; | ||
| 17913 | struct sfnt_gvar_table *gvar; | ||
| 16265 | sfnt_fixed scale; | 17914 | sfnt_fixed scale; |
| 16266 | char *fancy; | 17915 | char *fancy; |
| 16267 | int *advances; | 17916 | int *advances; |
| 16268 | struct sfnt_raster **rasters; | 17917 | struct sfnt_raster **rasters; |
| 16269 | size_t length; | 17918 | size_t length; |
| 17919 | char *axis_name; | ||
| 17920 | struct sfnt_instance *instance; | ||
| 17921 | struct sfnt_blend blend; | ||
| 16270 | 17922 | ||
| 16271 | if (argc < 2) | 17923 | if (argc < 2) |
| 16272 | return 1; | 17924 | return 1; |
| 16273 | 17925 | ||
| 17926 | instance = NULL; | ||
| 17927 | |||
| 16274 | if (!strcmp (argv[1], "--check-interpreter")) | 17928 | if (!strcmp (argv[1], "--check-interpreter")) |
| 16275 | { | 17929 | { |
| 16276 | interpreter = sfnt_make_test_interpreter (); | 17930 | interpreter = sfnt_make_test_interpreter (); |
| @@ -16324,7 +17978,7 @@ main (int argc, char **argv) | |||
| 16324 | font = sfnt_read_table_directory (fd); | 17978 | font = sfnt_read_table_directory (fd); |
| 16325 | } | 17979 | } |
| 16326 | 17980 | ||
| 16327 | if (!font) | 17981 | if (!font || font == (struct sfnt_offset_subtable *) -1) |
| 16328 | { | 17982 | { |
| 16329 | close (fd); | 17983 | close (fd); |
| 16330 | return 1; | 17984 | return 1; |
| @@ -16375,8 +18029,8 @@ main (int argc, char **argv) | |||
| 16375 | return 1; | 18029 | return 1; |
| 16376 | } | 18030 | } |
| 16377 | 18031 | ||
| 16378 | #define FANCY_PPEM 25 | 18032 | #define FANCY_PPEM 12 |
| 16379 | #define EASY_PPEM 25 | 18033 | #define EASY_PPEM 12 |
| 16380 | 18034 | ||
| 16381 | interpreter = NULL; | 18035 | interpreter = NULL; |
| 16382 | head = sfnt_read_head_table (fd, font); | 18036 | head = sfnt_read_head_table (fd, font); |
| @@ -16388,16 +18042,18 @@ main (int argc, char **argv) | |||
| 16388 | cvt = sfnt_read_cvt_table (fd, font); | 18042 | cvt = sfnt_read_cvt_table (fd, font); |
| 16389 | fpgm = sfnt_read_fpgm_table (fd, font); | 18043 | fpgm = sfnt_read_fpgm_table (fd, font); |
| 16390 | prep = sfnt_read_prep_table (fd, font); | 18044 | prep = sfnt_read_prep_table (fd, font); |
| 18045 | fvar = sfnt_read_fvar_table (fd, font); | ||
| 18046 | gvar = sfnt_read_gvar_table (fd, font); | ||
| 16391 | hmtx = NULL; | 18047 | hmtx = NULL; |
| 16392 | 18048 | ||
| 16393 | exec_prep = prep; | 18049 | exec_prep = prep; |
| 16394 | exec_fpgm = fpgm; | 18050 | exec_fpgm = fpgm; |
| 16395 | 18051 | fancy = getenv ("SFNT_FANCY_TEST"); | |
| 16396 | if (getenv ("SFNT_FANCY_TEST")) | 18052 | |
| 18053 | if (fancy) | ||
| 16397 | { | 18054 | { |
| 16398 | loca_long = NULL; | 18055 | loca_long = NULL; |
| 16399 | loca_short = NULL; | 18056 | loca_short = NULL; |
| 16400 | fancy = getenv ("SFNT_FANCY_TEST"); | ||
| 16401 | length = strlen (fancy); | 18057 | length = strlen (fancy); |
| 16402 | scale = sfnt_div_fixed (FANCY_PPEM, head->units_per_em); | 18058 | scale = sfnt_div_fixed (FANCY_PPEM, head->units_per_em); |
| 16403 | 18059 | ||
| @@ -16659,6 +18315,82 @@ main (int argc, char **argv) | |||
| 16659 | (int) hhea->caret_slope_rise, | 18315 | (int) hhea->caret_slope_rise, |
| 16660 | (int) hhea->caret_slope_run); | 18316 | (int) hhea->caret_slope_run); |
| 16661 | 18317 | ||
| 18318 | if (fvar) | ||
| 18319 | { | ||
| 18320 | fprintf (stderr, "FVAR table found!\n" | ||
| 18321 | "version: %"PRIu16".%"PRIu16"\n" | ||
| 18322 | "axis_count: %"PRIu16"\n" | ||
| 18323 | "axis_size: %"PRIu16"\n" | ||
| 18324 | "instance_count: %"PRIu16"\n" | ||
| 18325 | "instance_size: %"PRIu16"\n", | ||
| 18326 | fvar->major_version, | ||
| 18327 | fvar->minor_version, | ||
| 18328 | fvar->axis_count, | ||
| 18329 | fvar->axis_size, | ||
| 18330 | fvar->instance_count, | ||
| 18331 | fvar->instance_size); | ||
| 18332 | |||
| 18333 | for (i = 0; i < fvar->axis_count; ++i) | ||
| 18334 | { | ||
| 18335 | if (name) | ||
| 18336 | { | ||
| 18337 | axis_name | ||
| 18338 | = (char *) sfnt_find_name (name, fvar->axis[i].name_id, | ||
| 18339 | &record); | ||
| 18340 | |||
| 18341 | if (axis_name) | ||
| 18342 | fprintf (stderr, "axis no: %d; name: %.*s\n", | ||
| 18343 | i, record.length, axis_name); | ||
| 18344 | } | ||
| 18345 | |||
| 18346 | fprintf (stderr, " axis: %"PRIx32" %g %g %g\n", | ||
| 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 | { | ||
| 18355 | if (name) | ||
| 18356 | { | ||
| 18357 | axis_name | ||
| 18358 | = (char *) sfnt_find_name (name, fvar->instance[i].name_id, | ||
| 18359 | &record); | ||
| 18360 | |||
| 18361 | if (axis_name) | ||
| 18362 | fprintf (stderr, "instance no: %d; name: %.*s\n", | ||
| 18363 | i, record.length, axis_name); | ||
| 18364 | } | ||
| 18365 | } | ||
| 18366 | |||
| 18367 | if (fvar->instance_count > 1) | ||
| 18368 | { | ||
| 18369 | printf ("instance? "); | ||
| 18370 | |||
| 18371 | if (scanf ("%d", &i) == EOF) | ||
| 18372 | goto free_lab; | ||
| 18373 | |||
| 18374 | if (i < 0 || i >= fvar->instance_count) | ||
| 18375 | goto free_lab; | ||
| 18376 | |||
| 18377 | instance = &fvar->instance[i]; | ||
| 18378 | } | ||
| 18379 | } | ||
| 18380 | |||
| 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 | |||
| 16662 | while (true) | 18394 | while (true) |
| 16663 | { | 18395 | { |
| 16664 | printf ("table, character? "); | 18396 | printf ("table, character? "); |
| @@ -16696,6 +18428,14 @@ main (int argc, char **argv) | |||
| 16696 | dcontext.loca_short = loca_short; | 18428 | dcontext.loca_short = loca_short; |
| 16697 | dcontext.loca_long = loca_long; | 18429 | dcontext.loca_long = loca_long; |
| 16698 | 18430 | ||
| 18431 | if (glyph->simple && instance && gvar) | ||
| 18432 | { | ||
| 18433 | printf ("applying variations to simple glyph...\n"); | ||
| 18434 | |||
| 18435 | if (sfnt_vary_glyph (&blend, code, glyph)) | ||
| 18436 | printf ("variation failed!\n"); | ||
| 18437 | } | ||
| 18438 | |||
| 16699 | if (sfnt_decompose_glyph (glyph, sfnt_test_move_to, | 18439 | if (sfnt_decompose_glyph (glyph, sfnt_test_move_to, |
| 16700 | sfnt_test_line_to, | 18440 | sfnt_test_line_to, |
| 16701 | sfnt_test_curve_to, | 18441 | sfnt_test_curve_to, |
| @@ -16871,6 +18611,8 @@ main (int argc, char **argv) | |||
| 16871 | } | 18611 | } |
| 16872 | } | 18612 | } |
| 16873 | 18613 | ||
| 18614 | free_lab: | ||
| 18615 | |||
| 16874 | xfree (font); | 18616 | xfree (font); |
| 16875 | 18617 | ||
| 16876 | for (i = 0; i < table->num_subtables; ++i) | 18618 | for (i = 0; i < table->num_subtables; ++i) |
| @@ -16893,6 +18635,11 @@ main (int argc, char **argv) | |||
| 16893 | xfree (fpgm); | 18635 | xfree (fpgm); |
| 16894 | xfree (interpreter); | 18636 | xfree (interpreter); |
| 16895 | xfree (prep); | 18637 | xfree (prep); |
| 18638 | xfree (fvar); | ||
| 18639 | xfree (gvar); | ||
| 18640 | |||
| 18641 | if (instance && gvar) | ||
| 18642 | sfnt_free_blend (&blend); | ||
| 16896 | 18643 | ||
| 16897 | return 0; | 18644 | return 0; |
| 16898 | } | 18645 | } |
diff --git a/src/sfnt.h b/src/sfnt.h index 83d34bfb757..82fa343f51d 100644 --- a/src/sfnt.h +++ b/src/sfnt.h | |||
| @@ -53,6 +53,9 @@ enum sfnt_table | |||
| 53 | SFNT_TABLE_CVT , | 53 | SFNT_TABLE_CVT , |
| 54 | SFNT_TABLE_FPGM, | 54 | SFNT_TABLE_FPGM, |
| 55 | SFNT_TABLE_PREP, | 55 | SFNT_TABLE_PREP, |
| 56 | SFNT_TABLE_FVAR, | ||
| 57 | SFNT_TABLE_GVAR, | ||
| 58 | SFNT_TABLE_CVAR, | ||
| 56 | }; | 59 | }; |
| 57 | 60 | ||
| 58 | #define SFNT_ENDOF(type, field, type1) \ | 61 | #define SFNT_ENDOF(type, field, type1) \ |
| @@ -61,7 +64,14 @@ enum sfnt_table | |||
| 61 | /* Each of these structures must be aligned so that no compiler will | 64 | /* Each of these structures must be aligned so that no compiler will |
| 62 | ever generate padding bytes on platforms where the alignment | 65 | ever generate padding bytes on platforms where the alignment |
| 63 | requirements for uint32_t and uint16_t are no larger than 4 and 2 | 66 | requirements for uint32_t and uint16_t are no larger than 4 and 2 |
| 64 | bytes respectively. */ | 67 | bytes respectively. |
| 68 | |||
| 69 | Pointer types are assumed to impose an alignmnent requirement no | ||
| 70 | less than that of uint32_t. | ||
| 71 | |||
| 72 | If a table has more than one kind of variable-length subtable array | ||
| 73 | at the end, make sure to pad subsequent subtables | ||
| 74 | appropriately. */ | ||
| 65 | 75 | ||
| 66 | struct sfnt_offset_subtable | 76 | struct sfnt_offset_subtable |
| 67 | { | 77 | { |
| @@ -568,25 +578,25 @@ struct sfnt_simple_glyph | |||
| 568 | size_t number_of_points; | 578 | size_t number_of_points; |
| 569 | 579 | ||
| 570 | /* Array containing the last points of each contour. */ | 580 | /* Array containing the last points of each contour. */ |
| 571 | uint16_t *end_pts_of_contours; | 581 | uint16_t *restrict end_pts_of_contours; |
| 572 | 582 | ||
| 573 | /* Total number of bytes needed for instructions. */ | 583 | /* Total number of bytes needed for instructions. */ |
| 574 | uint16_t instruction_length; | 584 | uint16_t instruction_length; |
| 575 | 585 | ||
| 576 | /* Instruction data. */ | 586 | /* Instruction data. */ |
| 577 | uint8_t *instructions; | 587 | uint8_t *restrict instructions; |
| 578 | 588 | ||
| 579 | /* Array of flags. */ | 589 | /* Array of flags. */ |
| 580 | uint8_t *flags; | 590 | uint8_t *restrict flags; |
| 581 | 591 | ||
| 582 | /* Array of X coordinates. */ | 592 | /* Array of X coordinates. */ |
| 583 | int16_t *x_coordinates; | 593 | int16_t *restrict x_coordinates; |
| 584 | 594 | ||
| 585 | /* Array of Y coordinates. */ | 595 | /* Array of Y coordinates. */ |
| 586 | int16_t *y_coordinates; | 596 | int16_t *restrict y_coordinates; |
| 587 | 597 | ||
| 588 | /* Pointer to the end of that array. */ | 598 | /* Pointer to the end of that array. */ |
| 589 | int16_t *y_coordinates_end; | 599 | int16_t *restrict y_coordinates_end; |
| 590 | }; | 600 | }; |
| 591 | 601 | ||
| 592 | struct sfnt_compound_glyph_component | 602 | struct sfnt_compound_glyph_component |