[sfnt, truetype] Always provide default instance.

As documented in the OpenType specification, an entry for the
default instance may be omitted in the named instance table.  In
particular this means that even if there is no named instance table
in the font we actually do have a named instance, namely the default
instance.

For consistency, we always want the default instance in our list of
named instances.  If it is missing, we try to synthesize it.

* src/sfnt/sfobjs.c (sfnt_init_face): Check whether the default
instance is in the table of named instances.  Otherwise adjust
number of instances.

* src/truetype/ttgxvar.c: Include FT_TRUETYPE_IDS_H.
(TT_Get_MM_Var): Use `face->root.style_flags' as the number of named
instances.
Sythesize a named instance entry if necessary.
(tt_done_blend): Free `normalized_stylecoords'.
This commit is contained in:
Werner Lemberg 2017-03-06 20:45:44 +01:00
parent f27992f295
commit 27fee7f8c6
3 changed files with 162 additions and 19 deletions

View File

@ -1,3 +1,26 @@
2017-03-06 Werner Lemberg <wl@gnu.org>
[sfnt, truetype] Always provide default instance.
As documented in the OpenType specification, an entry for the
default instance may be omitted in the named instance table. In
particular this means that even if there is no named instance table
in the font we actually do have a named instance, namely the default
instance.
For consistency, we always want the default instance in our list of
named instances. If it is missing, we try to synthesize it.
* src/sfnt/sfobjs.c (sfnt_init_face): Check whether the default
instance is in the table of named instances. Otherwise adjust
number of instances.
* src/truetype/ttgxvar.c: Include FT_TRUETYPE_IDS_H.
(TT_Get_MM_Var): Use `face->root.style_flags' as the number of named
instances.
Sythesize a named instance entry if necessary.
(tt_done_blend): Free `normalized_stylecoords'.
2017-03-05 Werner Lemberg <wl@gnu.org>
[sfnt] Remove redundant code.

View File

@ -856,6 +856,7 @@
FT_Parameter* params )
{
FT_Error error;
FT_Memory memory = face->root.memory;
FT_Library library = face->root.driver->root.library;
SFNT_Service sfnt;
FT_Int face_index;
@ -954,6 +955,9 @@
FT_Int instance_index;
FT_Byte* default_values = NULL;
FT_Byte* instance_values = NULL;
face->is_default_instance = 1;
@ -999,6 +1003,65 @@
if ( !face->goto_table( face, TTAG_CFF, stream, 0 ) )
num_instances = 0;
/*
* As documented in the OpenType specification, an entry for the
* default instance may be omitted in the named instance table. In
* particular this means that even if there is no named instance
* table in the font we actually do have a named instance, namely the
* default instance.
*
* For consistency, we always want the default instance in our list
* of named instances. If it is missing, we try to synthesize it
* later on. Here, we have to adjust `num_instances' accordingly.
*/
if ( !( FT_ALLOC( default_values, num_axes * 2 ) ||
FT_ALLOC( instance_values, num_axes * 2 ) ) )
{
/* the current stream position is 16 bytes after the table start */
FT_ULong array_start = FT_STREAM_POS() - 16 + offset;
FT_ULong default_value_offset, instance_offset;
FT_Byte* p;
FT_UInt i;
default_value_offset = array_start + 8;
p = default_values;
for ( i = 0; i < num_axes; i++ )
{
(void)FT_STREAM_READ_AT( default_value_offset, p, 2 );
default_value_offset += axis_size;
p += 2;
}
instance_offset = array_start + axis_size * num_axes + 4;
for ( i = 0; i < num_instances; i++ )
{
(void)FT_STREAM_READ_AT( instance_offset,
instance_values,
num_axes * 2 );
if ( !ft_memcmp( default_values, instance_values, num_axes * 2 ) )
break;
instance_offset += instance_size;
}
if ( i == num_instances )
{
/* no default instance in named instance table; */
/* we thus have to synthesize it */
num_instances++;
}
}
FT_FREE( default_values );
FT_FREE( instance_values );
/* instance indices in `face_instance_index' start with index 1, */
/* thus `>' and not `>=' */
if ( instance_index > num_instances )

View File

@ -45,6 +45,7 @@
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
#include FT_TRUETYPE_TAGS_H
#include FT_TRUETYPE_IDS_H
#include FT_MULTIPLE_MASTERS_H
#include FT_LIST_H
@ -1930,15 +1931,17 @@
FT_ULong table_len;
FT_Error error = FT_Err_Ok;
FT_ULong fvar_start;
FT_Int i, j;
FT_UInt i, j;
FT_MM_Var* mmvar = NULL;
FT_Fixed* next_coords;
FT_Fixed* nsc;
FT_String* next_name;
FT_Var_Axis* a;
FT_Fixed* c;
FT_Var_Named_Style* ns;
GX_FVar_Head fvar_head;
FT_Bool usePsName;
FT_UInt num_instances;
static const FT_Frame_Field fvar_fields[] =
{
@ -2019,12 +2022,18 @@
if ( FT_NEW( face->blend ) )
goto Exit;
/* cannot overflow 32-bit arithmetic because of the validity check */
/* `num_instances' holds the number of all named instances, */
/* including the default instance which might be missing */
/* in fvar's table of named instances */
num_instances = face->root.style_flags >> 16;
/* cannot overflow 32-bit arithmetic because of the size limits */
/* used in the `fvar' table validity check in `sfnt_init_face' */
face->blend->mmvar_len =
sizeof ( FT_MM_Var ) +
fvar_head.axisCount * sizeof ( FT_Var_Axis ) +
fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) +
fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) +
num_instances * sizeof ( FT_Var_Named_Style ) +
num_instances * fvar_head.axisCount * sizeof ( FT_Fixed ) +
5 * fvar_head.axisCount;
if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
@ -2041,15 +2050,15 @@
/* may have a different number of designs */
/* (or tuples, as called by Apple) */
mmvar->num_namedstyles =
fvar_head.instanceCount;
num_instances;
mmvar->axis =
(FT_Var_Axis*)&( mmvar[1] );
mmvar->namedstyle =
(FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] );
next_coords =
(FT_Fixed*)&( mmvar->namedstyle[fvar_head.instanceCount] );
for ( i = 0; i < fvar_head.instanceCount; i++ )
(FT_Fixed*)&( mmvar->namedstyle[num_instances] );
for ( i = 0; i < num_instances; i++ )
{
mmvar->namedstyle[i].coords = next_coords;
next_coords += fvar_head.axisCount;
@ -2109,17 +2118,14 @@
FT_TRACE5(( "\n" ));
if ( fvar_head.instanceCount )
{
/* named instance coordinates are stored as design coordinates; */
/* we have to convert them to normalized coordinates also */
if ( FT_NEW_ARRAY( face->blend->normalized_stylecoords,
fvar_head.axisCount * fvar_head.instanceCount ) )
goto Exit;
/* named instance coordinates are stored as design coordinates; */
/* we have to convert them to normalized coordinates also */
if ( FT_NEW_ARRAY( face->blend->normalized_stylecoords,
fvar_head.axisCount * num_instances ) )
goto Exit;
if ( !face->blend->avar_checked )
ft_var_load_avar( face );
}
if ( fvar_head.instanceCount && !face->blend->avar_checked )
ft_var_load_avar( face );
ns = mmvar->namedstyle;
nsc = face->blend->normalized_stylecoords;
@ -2133,8 +2139,9 @@
ns->strid = FT_GET_USHORT();
(void) /* flags = */ FT_GET_USHORT();
for ( j = 0; j < fvar_head.axisCount; j++ )
ns->coords[j] = FT_GET_LONG();
c = ns->coords;
for ( j = 0; j < fvar_head.axisCount; j++, c++ )
*c = FT_GET_LONG();
if ( usePsName )
ns->psid = FT_GET_USHORT();
@ -2148,6 +2155,55 @@
FT_FRAME_EXIT();
}
if ( num_instances != fvar_head.instanceCount )
{
SFNT_Service sfnt = (SFNT_Service)face->sfnt;
FT_Int found, win, apple;
/* the default instance is missing in array the */
/* of named instances; try to synthesize an entry */
found = sfnt->get_name_id( face,
TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY,
&win,
&apple );
if ( !found )
found = sfnt->get_name_id( face,
TT_NAME_ID_FONT_SUBFAMILY,
&win,
&apple );
if ( found )
{
FT_Int strid = win >= 0 ? win : apple;
found = sfnt->get_name_id( face,
TT_NAME_ID_PS_NAME,
&win,
&apple );
if ( found )
{
FT_Int psid = win >= 0 ? win : apple;
FT_TRACE5(( "TT_Get_MM_Var:"
" Adding default instance to named instances\n" ));
ns = &mmvar->namedstyle[fvar_head.instanceCount];
ns->strid = strid;
ns->psid = psid;
a = mmvar->axis;
c = ns->coords;
for ( j = 0; j < fvar_head.axisCount; j++, a++, c++ )
*c = a->def;
}
}
}
ft_var_load_mvar( face );
}
@ -3528,6 +3584,7 @@
num_axes = blend->mmvar->num_axis;
FT_FREE( blend->normalizedcoords );
FT_FREE( blend->normalized_stylecoords );
FT_FREE( blend->mmvar );
if ( blend->avar_segment )