1 /****************************************************************************
2 *
3 * ttgxvar.c
4 *
5 * TrueType GX Font Variation loader
6 *
7 * Copyright (C) 2004-2019 by
8 * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
19 /**************************************************************************
20 *
21 * Apple documents the `fvar', `gvar', `cvar', and `avar' tables at
22 *
23 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html
24 *
25 * The documentation for `gvar' is not intelligible; `cvar' refers you
26 * to `gvar' and is thus also incomprehensible.
27 *
1453 * better be there too.
1454 *
1455 * @InOut:
1456 * face ::
1457 * The font face.
1458 *
1459 * @Return:
1460 * FreeType error code. 0 means success.
1461 */
1462 static FT_Error
1463 ft_var_load_gvar( TT_Face face )
1464 {
1465 FT_Stream stream = FT_FACE_STREAM( face );
1466 FT_Memory memory = stream->memory;
1467 GX_Blend blend = face->blend;
1468 FT_Error error;
1469 FT_UInt i, j;
1470 FT_ULong table_len;
1471 FT_ULong gvar_start;
1472 FT_ULong offsetToData;
1473 GX_GVar_Head gvar_head;
1474
1475 static const FT_Frame_Field gvar_fields[] =
1476 {
1477
1478 #undef FT_STRUCTURE
1479 #define FT_STRUCTURE GX_GVar_Head
1480
1481 FT_FRAME_START( 20 ),
1482 FT_FRAME_LONG ( version ),
1483 FT_FRAME_USHORT( axisCount ),
1484 FT_FRAME_USHORT( globalCoordCount ),
1485 FT_FRAME_ULONG ( offsetToCoord ),
1486 FT_FRAME_USHORT( glyphCount ),
1487 FT_FRAME_USHORT( flags ),
1488 FT_FRAME_ULONG ( offsetToData ),
1489 FT_FRAME_END
1490 };
1491
1492
1513 }
1514
1515 if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
1516 {
1517 FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
1518 " table are different\n" ));
1519 error = FT_THROW( Invalid_Table );
1520 goto Exit;
1521 }
1522
1523 /* rough sanity check, ignoring offsets */
1524 if ( (FT_ULong)gvar_head.globalCoordCount * gvar_head.axisCount >
1525 table_len / 2 )
1526 {
1527 FT_TRACE1(( "ft_var_load_gvar:"
1528 " invalid number of global coordinates\n" ));
1529 error = FT_THROW( Invalid_Table );
1530 goto Exit;
1531 }
1532
1533 /* rough sanity check: offsets can be either 2 or 4 bytes */
1534 if ( (FT_ULong)gvar_head.glyphCount *
1535 ( ( gvar_head.flags & 1 ) ? 4 : 2 ) > table_len )
1536 {
1537 FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" ));
1538 error = FT_THROW( Invalid_Table );
1539 goto Exit;
1540 }
1541
1542 FT_TRACE2(( "loaded\n" ));
1543
1544 blend->gvar_size = table_len;
1545 blend->tuplecount = gvar_head.globalCoordCount;
1546 blend->gv_glyphcnt = gvar_head.glyphCount;
1547 offsetToData = gvar_start + gvar_head.offsetToData;
1548
1549 FT_TRACE5(( "gvar: there %s %d shared coordinate%s:\n",
1550 blend->tuplecount == 1 ? "is" : "are",
1551 blend->tuplecount,
1552 blend->tuplecount == 1 ? "" : "s" ));
1553
1554 if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
1555 goto Exit;
1556
1557 if ( gvar_head.flags & 1 )
1558 {
1559 FT_ULong limit = gvar_start + table_len;
1560
1561
1562 /* long offsets (one more offset than glyphs, to mark size of last) */
1563 if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
1564 goto Exit;
1565
1566 for ( i = 0; i <= blend->gv_glyphcnt; i++ )
1567 {
1568 blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
1569 /* use `>', not `>=' */
1570 if ( blend->glyphoffsets[i] > limit )
1571 {
1572 FT_TRACE2(( "ft_var_load_gvar:"
1573 " invalid glyph variation data offset for index %d\n",
1574 i ));
1575 error = FT_THROW( Invalid_Table );
1576 break;
1577 }
1578 }
1579 }
1580 else
1581 {
1582 FT_ULong limit = gvar_start + table_len;
1583
1584
1585 /* short offsets (one more offset than glyphs, to mark size of last) */
1586 if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
1587 goto Exit;
1588
1589 for ( i = 0; i <= blend->gv_glyphcnt; i++ )
1590 {
1591 blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
1592 /* use `>', not `>=' */
1593 if ( blend->glyphoffsets[i] > limit )
1594 {
1595 FT_TRACE2(( "ft_var_load_gvar:"
1596 " invalid glyph variation data offset for index %d\n",
1597 i ));
1598 error = FT_THROW( Invalid_Table );
1599 break;
1600 }
1601 }
1602 }
1603
1604 FT_FRAME_EXIT();
1605 if ( error )
1606 goto Exit;
1607
1608 if ( blend->tuplecount != 0 )
1609 {
1610 if ( FT_NEW_ARRAY( blend->tuplecoords,
1611 gvar_head.axisCount * blend->tuplecount ) )
1612 goto Exit;
1613
1614 if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
1615 FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )
1616 goto Exit;
1617
1618 for ( i = 0; i < blend->tuplecount; i++ )
1619 {
1620 FT_TRACE5(( " [ " ));
1621 for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ )
1622 {
1623 blend->tuplecoords[i * gvar_head.axisCount + j] =
1624 FT_fdot14ToFixed( FT_GET_SHORT() );
1625 FT_TRACE5(( "%.5f ",
1626 blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
1627 }
1628 FT_TRACE5(( "]\n" ));
1629 }
1630
1631 FT_TRACE5(( "\n" ));
1632
1633 FT_FRAME_EXIT();
1634 }
1635
1636 Exit:
1637 return error;
1638 }
1639
1640
1641 /**************************************************************************
1642 *
1643 * @Function:
1644 * ft_var_apply_tuple
1645 *
1646 * @Description:
1647 * Figure out whether a given tuple (design) applies to the current
1648 * blend, and if so, what is the scaling factor.
1649 *
1650 * @Input:
1651 * blend ::
1652 * The current blend of the font.
1653 *
1654 * tupleIndex ::
1655 * A flag saying whether this is an intermediate
1656 * tuple or not.
1657 *
2110
2111 if ( FT_NEW( face->blend ) )
2112 goto Exit;
2113
2114 num_axes = fvar_head.axisCount;
2115 face->blend->num_axis = num_axes;
2116 }
2117 else
2118 num_axes = face->blend->num_axis;
2119
2120 /* `num_instances' holds the number of all named instances, */
2121 /* including the default instance which might be missing */
2122 /* in fvar's table of named instances */
2123 num_instances = (FT_UInt)face->root.style_flags >> 16;
2124
2125 /* prepare storage area for MM data; this cannot overflow */
2126 /* 32-bit arithmetic because of the size limits used in the */
2127 /* `fvar' table validity check in `sfnt_init_face' */
2128
2129 /* the various `*_size' variables, which we also use as */
2130 /* offsets into the `mmlen' array, must be multiples of the */
2131 /* pointer size (except the last one); without such an */
2132 /* alignment there might be runtime errors due to */
2133 /* misaligned addresses */
2134 #undef ALIGN_SIZE
2135 #define ALIGN_SIZE( n ) \
2136 ( ( (n) + sizeof (void*) - 1 ) & ~( sizeof (void*) - 1 ) )
2137
2138 mmvar_size = ALIGN_SIZE( sizeof ( FT_MM_Var ) );
2139 axis_flags_size = ALIGN_SIZE( num_axes *
2140 sizeof ( FT_UShort ) );
2141 axis_size = ALIGN_SIZE( num_axes *
2142 sizeof ( FT_Var_Axis ) );
2143 namedstyle_size = ALIGN_SIZE( num_instances *
2144 sizeof ( FT_Var_Named_Style ) );
2145 next_coords_size = ALIGN_SIZE( num_instances *
2146 num_axes *
2147 sizeof ( FT_Fixed ) );
2148 next_name_size = num_axes * 5;
2149
2150 if ( need_init )
3020 *
3021 * @Description:
3022 * Set the given named instance, also resetting any further
3023 * variation.
3024 *
3025 * @Input:
3026 * face ::
3027 * A handle to the source face.
3028 *
3029 * instance_index ::
3030 * The instance index, starting with value 1.
3031 * Value 0 indicates to not use an instance.
3032 *
3033 * @Return:
3034 * FreeType error code. 0~means success.
3035 */
3036 FT_LOCAL_DEF( FT_Error )
3037 TT_Set_Named_Instance( TT_Face face,
3038 FT_UInt instance_index )
3039 {
3040 FT_Error error = FT_ERR( Invalid_Argument );
3041 GX_Blend blend;
3042 FT_MM_Var* mmvar;
3043
3044 FT_UInt num_instances;
3045
3046
3047 if ( !face->blend )
3048 {
3049 if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
3050 goto Exit;
3051 }
3052
3053 blend = face->blend;
3054 mmvar = blend->mmvar;
3055
3056 num_instances = (FT_UInt)face->root.style_flags >> 16;
3057
3058 /* `instance_index' starts with value 1, thus `>' */
3059 if ( instance_index > num_instances )
3060 goto Exit;
3061
3062 if ( instance_index > 0 )
3063 {
3064 FT_Memory memory = face->root.memory;
3065 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
3066
3067 FT_Var_Named_Style* named_style;
3068 FT_String* style_name;
3069
3070
3071 named_style = mmvar->namedstyle + instance_index - 1;
3072
3073 error = sfnt->get_name( face,
3074 (FT_UShort)named_style->strid,
3075 &style_name );
3076 if ( error )
3077 goto Exit;
3078
3079 /* set (or replace) style name */
3080 FT_FREE( face->root.style_name );
3749 FT_Fixed* deltas_x = NULL;
3750 FT_Fixed* deltas_y = NULL;
3751 FT_Fixed* point_deltas_x = NULL;
3752 FT_Fixed* point_deltas_y = NULL;
3753
3754
3755 if ( !face->doblend || !blend )
3756 return FT_THROW( Invalid_Argument );
3757
3758 for ( i = 0; i < n_points; i++ )
3759 {
3760 unrounded[i].x = INT_TO_F26DOT6( outline->points[i].x );
3761 unrounded[i].y = INT_TO_F26DOT6( outline->points[i].y );
3762 }
3763
3764 if ( glyph_index >= blend->gv_glyphcnt ||
3765 blend->glyphoffsets[glyph_index] ==
3766 blend->glyphoffsets[glyph_index + 1] )
3767 {
3768 FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
3769 " no variation data for this glyph\n" ));
3770 return FT_Err_Ok;
3771 }
3772
3773 if ( FT_NEW_ARRAY( points_org, n_points ) ||
3774 FT_NEW_ARRAY( points_out, n_points ) ||
3775 FT_NEW_ARRAY( has_delta, n_points ) )
3776 goto Fail1;
3777
3778 dataSize = blend->glyphoffsets[glyph_index + 1] -
3779 blend->glyphoffsets[glyph_index];
3780
3781 if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
3782 FT_FRAME_ENTER( dataSize ) )
3783 goto Fail1;
3784
3785 glyph_start = FT_Stream_FTell( stream );
3786
3787 /* each set of glyph variation data is formatted similarly to `cvar' */
3788
3789 if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
|
1 /****************************************************************************
2 *
3 * ttgxvar.c
4 *
5 * TrueType GX Font Variation loader
6 *
7 * Copyright (C) 2004-2020 by
8 * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
19 /**************************************************************************
20 *
21 * Apple documents the `fvar', `gvar', `cvar', and `avar' tables at
22 *
23 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html
24 *
25 * The documentation for `gvar' is not intelligible; `cvar' refers you
26 * to `gvar' and is thus also incomprehensible.
27 *
1453 * better be there too.
1454 *
1455 * @InOut:
1456 * face ::
1457 * The font face.
1458 *
1459 * @Return:
1460 * FreeType error code. 0 means success.
1461 */
1462 static FT_Error
1463 ft_var_load_gvar( TT_Face face )
1464 {
1465 FT_Stream stream = FT_FACE_STREAM( face );
1466 FT_Memory memory = stream->memory;
1467 GX_Blend blend = face->blend;
1468 FT_Error error;
1469 FT_UInt i, j;
1470 FT_ULong table_len;
1471 FT_ULong gvar_start;
1472 FT_ULong offsetToData;
1473 FT_ULong offsets_len;
1474 GX_GVar_Head gvar_head;
1475
1476 static const FT_Frame_Field gvar_fields[] =
1477 {
1478
1479 #undef FT_STRUCTURE
1480 #define FT_STRUCTURE GX_GVar_Head
1481
1482 FT_FRAME_START( 20 ),
1483 FT_FRAME_LONG ( version ),
1484 FT_FRAME_USHORT( axisCount ),
1485 FT_FRAME_USHORT( globalCoordCount ),
1486 FT_FRAME_ULONG ( offsetToCoord ),
1487 FT_FRAME_USHORT( glyphCount ),
1488 FT_FRAME_USHORT( flags ),
1489 FT_FRAME_ULONG ( offsetToData ),
1490 FT_FRAME_END
1491 };
1492
1493
1514 }
1515
1516 if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
1517 {
1518 FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
1519 " table are different\n" ));
1520 error = FT_THROW( Invalid_Table );
1521 goto Exit;
1522 }
1523
1524 /* rough sanity check, ignoring offsets */
1525 if ( (FT_ULong)gvar_head.globalCoordCount * gvar_head.axisCount >
1526 table_len / 2 )
1527 {
1528 FT_TRACE1(( "ft_var_load_gvar:"
1529 " invalid number of global coordinates\n" ));
1530 error = FT_THROW( Invalid_Table );
1531 goto Exit;
1532 }
1533
1534 /* offsets can be either 2 or 4 bytes */
1535 /* (one more offset than glyphs, to mark size of last) */
1536 offsets_len = ( gvar_head.glyphCount + 1 ) *
1537 ( ( gvar_head.flags & 1 ) ? 4L : 2L );
1538
1539 /* rough sanity check */
1540 if (offsets_len > table_len )
1541 {
1542 FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" ));
1543 error = FT_THROW( Invalid_Table );
1544 goto Exit;
1545 }
1546
1547 FT_TRACE2(( "loaded\n" ));
1548
1549 blend->gvar_size = table_len;
1550 offsetToData = gvar_start + gvar_head.offsetToData;
1551
1552 FT_TRACE5(( "gvar: there %s %d shared coordinate%s:\n",
1553 gvar_head.globalCoordCount == 1 ? "is" : "are",
1554 gvar_head.globalCoordCount,
1555 gvar_head.globalCoordCount == 1 ? "" : "s" ));
1556
1557 if ( FT_FRAME_ENTER( offsets_len ) )
1558 goto Exit;
1559
1560 /* offsets (one more offset than glyphs, to mark size of last) */
1561 if ( FT_NEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) )
1562 goto Fail2;
1563
1564 if ( gvar_head.flags & 1 )
1565 {
1566 FT_ULong limit = gvar_start + table_len;
1567 FT_ULong max_offset = 0;
1568
1569
1570 for ( i = 0; i <= gvar_head.glyphCount; i++ )
1571 {
1572 blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
1573
1574 if ( max_offset <= blend->glyphoffsets[i] )
1575 max_offset = blend->glyphoffsets[i];
1576 else
1577 {
1578 FT_TRACE2(( "ft_var_load_gvar:"
1579 " glyph variation data offset %d not monotonic\n",
1580 i ));
1581 blend->glyphoffsets[i] = max_offset;
1582 }
1583
1584 /* use `<', not `<=' */
1585 if ( limit < blend->glyphoffsets[i] )
1586 {
1587 FT_TRACE2(( "ft_var_load_gvar:"
1588 " glyph variation data offset %d out of range\n",
1589 i ));
1590 blend->glyphoffsets[i] = limit;
1591 }
1592 }
1593 }
1594 else
1595 {
1596 FT_ULong limit = gvar_start + table_len;
1597 FT_ULong max_offset = 0;
1598
1599
1600 for ( i = 0; i <= gvar_head.glyphCount; i++ )
1601 {
1602 blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
1603
1604 if ( max_offset <= blend->glyphoffsets[i] )
1605 max_offset = blend->glyphoffsets[i];
1606 else
1607 {
1608 FT_TRACE2(( "ft_var_load_gvar:"
1609 " glyph variation data offset %d not monotonic\n",
1610 i ));
1611 blend->glyphoffsets[i] = max_offset;
1612 }
1613
1614 /* use `<', not `<=' */
1615 if ( limit < blend->glyphoffsets[i] )
1616 {
1617 FT_TRACE2(( "ft_var_load_gvar:"
1618 " glyph variation data offset %d out of range\n",
1619 i ));
1620 blend->glyphoffsets[i] = limit;
1621 }
1622 }
1623 }
1624
1625 blend->gv_glyphcnt = gvar_head.glyphCount;
1626
1627 FT_FRAME_EXIT();
1628
1629 if ( gvar_head.globalCoordCount != 0 )
1630 {
1631 if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
1632 FT_FRAME_ENTER( gvar_head.globalCoordCount *
1633 gvar_head.axisCount * 2L ) )
1634 {
1635 FT_TRACE2(( "ft_var_load_gvar:"
1636 " glyph variation shared tuples missing\n" ));
1637 goto Fail;
1638 }
1639
1640 if ( FT_NEW_ARRAY( blend->tuplecoords,
1641 gvar_head.axisCount * gvar_head.globalCoordCount ) )
1642 goto Fail2;
1643
1644 for ( i = 0; i < gvar_head.globalCoordCount; i++ )
1645 {
1646 FT_TRACE5(( " [ " ));
1647 for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ )
1648 {
1649 blend->tuplecoords[i * gvar_head.axisCount + j] =
1650 FT_fdot14ToFixed( FT_GET_SHORT() );
1651 FT_TRACE5(( "%.5f ",
1652 blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
1653 }
1654 FT_TRACE5(( "]\n" ));
1655 }
1656
1657 blend->tuplecount = gvar_head.globalCoordCount;
1658
1659 FT_TRACE5(( "\n" ));
1660
1661 FT_FRAME_EXIT();
1662 }
1663
1664 Exit:
1665 return error;
1666
1667 Fail2:
1668 FT_FRAME_EXIT();
1669
1670 Fail:
1671 FT_FREE( blend->glyphoffsets );
1672 blend->gv_glyphcnt = 0;
1673 goto Exit;
1674 }
1675
1676
1677 /**************************************************************************
1678 *
1679 * @Function:
1680 * ft_var_apply_tuple
1681 *
1682 * @Description:
1683 * Figure out whether a given tuple (design) applies to the current
1684 * blend, and if so, what is the scaling factor.
1685 *
1686 * @Input:
1687 * blend ::
1688 * The current blend of the font.
1689 *
1690 * tupleIndex ::
1691 * A flag saying whether this is an intermediate
1692 * tuple or not.
1693 *
2146
2147 if ( FT_NEW( face->blend ) )
2148 goto Exit;
2149
2150 num_axes = fvar_head.axisCount;
2151 face->blend->num_axis = num_axes;
2152 }
2153 else
2154 num_axes = face->blend->num_axis;
2155
2156 /* `num_instances' holds the number of all named instances, */
2157 /* including the default instance which might be missing */
2158 /* in fvar's table of named instances */
2159 num_instances = (FT_UInt)face->root.style_flags >> 16;
2160
2161 /* prepare storage area for MM data; this cannot overflow */
2162 /* 32-bit arithmetic because of the size limits used in the */
2163 /* `fvar' table validity check in `sfnt_init_face' */
2164
2165 /* the various `*_size' variables, which we also use as */
2166 /* offsets into the `mmvar' array, must be multiples of the */
2167 /* pointer size (except the last one); without such an */
2168 /* alignment there might be runtime errors due to */
2169 /* misaligned addresses */
2170 #undef ALIGN_SIZE
2171 #define ALIGN_SIZE( n ) \
2172 ( ( (n) + sizeof (void*) - 1 ) & ~( sizeof (void*) - 1 ) )
2173
2174 mmvar_size = ALIGN_SIZE( sizeof ( FT_MM_Var ) );
2175 axis_flags_size = ALIGN_SIZE( num_axes *
2176 sizeof ( FT_UShort ) );
2177 axis_size = ALIGN_SIZE( num_axes *
2178 sizeof ( FT_Var_Axis ) );
2179 namedstyle_size = ALIGN_SIZE( num_instances *
2180 sizeof ( FT_Var_Named_Style ) );
2181 next_coords_size = ALIGN_SIZE( num_instances *
2182 num_axes *
2183 sizeof ( FT_Fixed ) );
2184 next_name_size = num_axes * 5;
2185
2186 if ( need_init )
3056 *
3057 * @Description:
3058 * Set the given named instance, also resetting any further
3059 * variation.
3060 *
3061 * @Input:
3062 * face ::
3063 * A handle to the source face.
3064 *
3065 * instance_index ::
3066 * The instance index, starting with value 1.
3067 * Value 0 indicates to not use an instance.
3068 *
3069 * @Return:
3070 * FreeType error code. 0~means success.
3071 */
3072 FT_LOCAL_DEF( FT_Error )
3073 TT_Set_Named_Instance( TT_Face face,
3074 FT_UInt instance_index )
3075 {
3076 FT_Error error;
3077 GX_Blend blend;
3078 FT_MM_Var* mmvar;
3079
3080 FT_UInt num_instances;
3081
3082
3083 if ( !face->blend )
3084 {
3085 if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
3086 goto Exit;
3087 }
3088
3089 blend = face->blend;
3090 mmvar = blend->mmvar;
3091
3092 num_instances = (FT_UInt)face->root.style_flags >> 16;
3093
3094 /* `instance_index' starts with value 1, thus `>' */
3095 if ( instance_index > num_instances )
3096 {
3097 error = FT_ERR( Invalid_Argument );
3098 goto Exit;
3099 }
3100
3101 if ( instance_index > 0 )
3102 {
3103 FT_Memory memory = face->root.memory;
3104 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
3105
3106 FT_Var_Named_Style* named_style;
3107 FT_String* style_name;
3108
3109
3110 named_style = mmvar->namedstyle + instance_index - 1;
3111
3112 error = sfnt->get_name( face,
3113 (FT_UShort)named_style->strid,
3114 &style_name );
3115 if ( error )
3116 goto Exit;
3117
3118 /* set (or replace) style name */
3119 FT_FREE( face->root.style_name );
3788 FT_Fixed* deltas_x = NULL;
3789 FT_Fixed* deltas_y = NULL;
3790 FT_Fixed* point_deltas_x = NULL;
3791 FT_Fixed* point_deltas_y = NULL;
3792
3793
3794 if ( !face->doblend || !blend )
3795 return FT_THROW( Invalid_Argument );
3796
3797 for ( i = 0; i < n_points; i++ )
3798 {
3799 unrounded[i].x = INT_TO_F26DOT6( outline->points[i].x );
3800 unrounded[i].y = INT_TO_F26DOT6( outline->points[i].y );
3801 }
3802
3803 if ( glyph_index >= blend->gv_glyphcnt ||
3804 blend->glyphoffsets[glyph_index] ==
3805 blend->glyphoffsets[glyph_index + 1] )
3806 {
3807 FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
3808 " no variation data for glyph %d\n", glyph_index ));
3809 return FT_Err_Ok;
3810 }
3811
3812 if ( FT_NEW_ARRAY( points_org, n_points ) ||
3813 FT_NEW_ARRAY( points_out, n_points ) ||
3814 FT_NEW_ARRAY( has_delta, n_points ) )
3815 goto Fail1;
3816
3817 dataSize = blend->glyphoffsets[glyph_index + 1] -
3818 blend->glyphoffsets[glyph_index];
3819
3820 if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
3821 FT_FRAME_ENTER( dataSize ) )
3822 goto Fail1;
3823
3824 glyph_start = FT_Stream_FTell( stream );
3825
3826 /* each set of glyph variation data is formatted similarly to `cvar' */
3827
3828 if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
|