mirror of https://github.com/freetype/freetype
[sfnt] Support `name' table format 1.
* include/freetype/internal/tttypes.h (TT_LangTagRec): New structure. (TT_NameTableRec): Add fields `numLangTagRecords' and `langTags'. * src/sfnt/ttload.c (tt_face_load_name): Add support for language tags. Reduce array size of name strings in case of invalid entries. (tt_face_free_name): Updated. * docs/CHANGES: Updated.
This commit is contained in:
parent
f4e5696643
commit
939df42072
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2017-01-26 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[sfnt] Support `name' table format 1.
|
||||
|
||||
* include/freetype/internal/tttypes.h (TT_LangTagRec): New
|
||||
structure.
|
||||
(TT_NameTableRec): Add fields `numLangTagRecords' and `langTags'.
|
||||
|
||||
* src/sfnt/ttload.c (tt_face_load_name): Add support for language
|
||||
tags.
|
||||
Reduce array size of name strings in case of invalid entries.
|
||||
(tt_face_free_name): Updated.
|
||||
|
||||
* docs/CHANGES: Updated.
|
||||
|
||||
2017-01-25 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[sfnt] s/TT_NameEntry/TT_Name/.
|
||||
|
|
|
@ -39,6 +39,13 @@ CHANGES BETWEEN 2.7.1 and 2.7.2
|
|||
|
||||
The old macro names are deprecated (but still available).
|
||||
|
||||
- Support for SFNT `name' tables has been improved.
|
||||
|
||||
. Format 1 `name' tables are now supported.
|
||||
|
||||
. Language ID and name ID values have been updated to OpenType version
|
||||
1.8.1.
|
||||
|
||||
|
||||
======================================================================
|
||||
|
||||
|
|
|
@ -279,11 +279,41 @@ FT_BEGIN_HEADER
|
|||
/* this last field is not defined in the spec */
|
||||
/* but used by the FreeType engine */
|
||||
|
||||
FT_Byte* string;
|
||||
FT_Byte* string;
|
||||
|
||||
} TT_NameRec, *TT_Name;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Struct> */
|
||||
/* TT_LangTagRec */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* A structure modeling language tag records in SFNT `name' tables, */
|
||||
/* introduced in OpenType version 1.6. */
|
||||
/* */
|
||||
/* <Fields> */
|
||||
/* stringLength :: The length of the string in bytes. */
|
||||
/* */
|
||||
/* stringOffset :: The offset to the string in the `name' table. */
|
||||
/* */
|
||||
/* string :: A pointer to the string's bytes. Note that these */
|
||||
/* are UTF-16BE encoded characters. */
|
||||
/* */
|
||||
typedef struct TT_LangTagRec_
|
||||
{
|
||||
FT_UShort stringLength;
|
||||
FT_ULong stringOffset;
|
||||
|
||||
/* this last field is not defined in the spec */
|
||||
/* but used by the FreeType engine */
|
||||
|
||||
FT_Byte* string;
|
||||
|
||||
} TT_LangTagRec, *TT_LangTag;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Struct> */
|
||||
|
@ -293,24 +323,30 @@ FT_BEGIN_HEADER
|
|||
/* A structure modeling the TrueType name table. */
|
||||
/* */
|
||||
/* <Fields> */
|
||||
/* format :: The format of the name table. */
|
||||
/* format :: The format of the name table. */
|
||||
/* */
|
||||
/* numNameRecords :: The number of names in table. */
|
||||
/* numNameRecords :: The number of names in table. */
|
||||
/* */
|
||||
/* storageOffset :: The offset of the name table in the `name' */
|
||||
/* TrueType table. */
|
||||
/* storageOffset :: The offset of the name table in the `name' */
|
||||
/* TrueType table. */
|
||||
/* */
|
||||
/* names :: An array of name records. */
|
||||
/* names :: An array of name records. */
|
||||
/* */
|
||||
/* stream :: the file's input stream. */
|
||||
/* numLangTagRecords :: The number of language tags in table. */
|
||||
/* */
|
||||
/* langTags :: An array of language tag records. */
|
||||
/* */
|
||||
/* stream :: The file's input stream. */
|
||||
/* */
|
||||
typedef struct TT_NameTableRec_
|
||||
{
|
||||
FT_UShort format;
|
||||
FT_UInt numNameRecords;
|
||||
FT_UInt storageOffset;
|
||||
TT_NameRec* names;
|
||||
FT_Stream stream;
|
||||
FT_UShort format;
|
||||
FT_UInt numNameRecords;
|
||||
FT_UInt storageOffset;
|
||||
TT_NameRec* names;
|
||||
FT_UInt numLangTagRecords;
|
||||
TT_LangTagRec* langTags;
|
||||
FT_Stream stream;
|
||||
|
||||
} TT_NameTableRec, *TT_NameTable;
|
||||
|
||||
|
|
|
@ -808,7 +808,6 @@
|
|||
FT_Memory memory = stream->memory;
|
||||
FT_ULong table_pos, table_len;
|
||||
FT_ULong storage_start, storage_limit;
|
||||
FT_UInt count;
|
||||
TT_NameTable table;
|
||||
|
||||
static const FT_Frame_Field name_table_fields[] =
|
||||
|
@ -838,6 +837,17 @@
|
|||
FT_FRAME_END
|
||||
};
|
||||
|
||||
static const FT_Frame_Field langTag_record_fields[] =
|
||||
{
|
||||
#undef FT_STRUCTURE
|
||||
#define FT_STRUCTURE TT_LangTagRec
|
||||
|
||||
/* no FT_FRAME_START */
|
||||
FT_FRAME_USHORT( stringLength ),
|
||||
FT_FRAME_USHORT( stringOffset ),
|
||||
FT_FRAME_END
|
||||
};
|
||||
|
||||
|
||||
table = &face->name_table;
|
||||
table->stream = stream;
|
||||
|
@ -848,18 +858,17 @@
|
|||
|
||||
table_pos = FT_STREAM_POS();
|
||||
|
||||
|
||||
if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
|
||||
goto Exit;
|
||||
|
||||
/* Some popular Asian fonts have an invalid `storageOffset' value */
|
||||
/* (it should be at least "6 + 12*num_names"). However, the string */
|
||||
/* offsets, computed as "storageOffset + entry->stringOffset", are */
|
||||
/* valid pointers within the name table... */
|
||||
/* */
|
||||
/* We thus can't check `storageOffset' right now. */
|
||||
/* */
|
||||
storage_start = table_pos + 6 + 12*table->numNameRecords;
|
||||
/* Some popular Asian fonts have an invalid `storageOffset' value (it */
|
||||
/* should be at least `6 + 12*numNameRecords'). However, the string */
|
||||
/* offsets, computed as `storageOffset + entry->stringOffset', are */
|
||||
/* valid pointers within the name table... */
|
||||
/* */
|
||||
/* We thus can't check `storageOffset' right now. */
|
||||
/* */
|
||||
storage_start = table_pos + 6 + 12 * table->numNameRecords;
|
||||
storage_limit = table_pos + table_len;
|
||||
|
||||
if ( storage_start > storage_limit )
|
||||
|
@ -869,18 +878,56 @@
|
|||
goto Exit;
|
||||
}
|
||||
|
||||
/* Allocate the array of name records. */
|
||||
count = table->numNameRecords;
|
||||
table->numNameRecords = 0;
|
||||
/* `name' format 1 contains additional language tag records, */
|
||||
/* which we load first */
|
||||
if ( table->format == 1 )
|
||||
{
|
||||
if ( FT_STREAM_SEEK( storage_start ) ||
|
||||
FT_READ_USHORT( table->numLangTagRecords ) )
|
||||
goto Exit;
|
||||
|
||||
if ( FT_NEW_ARRAY( table->names, count ) ||
|
||||
FT_FRAME_ENTER( count * 12 ) )
|
||||
storage_start += 2 + 4 * table->numLangTagRecords;
|
||||
|
||||
/* allocate language tag records array */
|
||||
if ( FT_NEW_ARRAY( table->langTags, table->numLangTagRecords ) ||
|
||||
FT_FRAME_ENTER( table->numLangTagRecords * 4 ) )
|
||||
goto Exit;
|
||||
|
||||
/* load language tags */
|
||||
{
|
||||
TT_LangTag entry = table->langTags;
|
||||
TT_LangTag limit = entry + table->numLangTagRecords;
|
||||
|
||||
|
||||
for ( ; entry < limit; entry++ )
|
||||
{
|
||||
(void)FT_STREAM_READ_FIELDS( langTag_record_fields, entry );
|
||||
|
||||
/* check that the langTag string is within the table */
|
||||
entry->stringOffset += table_pos + table->storageOffset;
|
||||
if ( entry->stringOffset < storage_start ||
|
||||
entry->stringOffset + entry->stringLength > storage_limit )
|
||||
{
|
||||
/* invalid entry; ignore it */
|
||||
entry->stringLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
(void)FT_STREAM_SEEK( table_pos + 6 );
|
||||
}
|
||||
|
||||
/* allocate name records array */
|
||||
if ( FT_NEW_ARRAY( table->names, table->numNameRecords ) ||
|
||||
FT_FRAME_ENTER( table->numNameRecords * 12 ) )
|
||||
goto Exit;
|
||||
|
||||
/* Load the name records and determine how much storage is needed */
|
||||
/* to hold the strings themselves. */
|
||||
/* load name records */
|
||||
{
|
||||
TT_Name entry = table->names;
|
||||
FT_UInt count = table->numNameRecords;
|
||||
|
||||
|
||||
for ( ; count > 0; count-- )
|
||||
|
@ -897,22 +944,37 @@
|
|||
if ( entry->stringOffset < storage_start ||
|
||||
entry->stringOffset + entry->stringLength > storage_limit )
|
||||
{
|
||||
/* invalid entry - ignore it */
|
||||
entry->stringOffset = 0;
|
||||
entry->stringLength = 0;
|
||||
/* invalid entry; ignore it */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* assure that we have a valid language tag ID, and */
|
||||
/* that the corresponding langTag entry is valid, too */
|
||||
if ( table->format == 1 && entry->languageID >= 0x8000U )
|
||||
{
|
||||
if ( entry->languageID - 0x8000U >= table->numLangTagRecords ||
|
||||
!table->langTags[entry->languageID - 0x8000U].stringLength )
|
||||
{
|
||||
/* invalid entry; ignore it */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
entry++;
|
||||
}
|
||||
|
||||
table->numNameRecords = (FT_UInt)( entry - table->names );
|
||||
/* reduce array size to the actually used elements */
|
||||
count = (FT_UInt)( entry - table->names );
|
||||
(void)FT_RENEW_ARRAY( table->names,
|
||||
table->numNameRecords,
|
||||
count );
|
||||
table->numNameRecords = count;
|
||||
}
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
/* everything went well, update face->num_names */
|
||||
face->num_names = (FT_UShort) table->numNameRecords;
|
||||
face->num_names = (FT_UShort)table->numNameRecords;
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
|
@ -935,25 +997,36 @@
|
|||
{
|
||||
FT_Memory memory = face->root.driver->root.memory;
|
||||
TT_NameTable table = &face->name_table;
|
||||
TT_Name entry = table->names;
|
||||
FT_UInt count = table->numNameRecords;
|
||||
|
||||
|
||||
if ( table->names )
|
||||
{
|
||||
for ( ; count > 0; count--, entry++ )
|
||||
{
|
||||
FT_FREE( entry->string );
|
||||
entry->stringLength = 0;
|
||||
}
|
||||
TT_Name entry = table->names;
|
||||
TT_Name limit = entry + table->numNameRecords;
|
||||
|
||||
|
||||
for ( ; entry < limit; entry++ )
|
||||
FT_FREE( entry->string );
|
||||
|
||||
/* free strings table */
|
||||
FT_FREE( table->names );
|
||||
}
|
||||
|
||||
table->numNameRecords = 0;
|
||||
table->format = 0;
|
||||
table->storageOffset = 0;
|
||||
if ( table->langTags )
|
||||
{
|
||||
TT_LangTag entry = table->langTags;
|
||||
TT_LangTag limit = entry + table->numLangTagRecords;
|
||||
|
||||
|
||||
for ( ; entry < limit; entry++ )
|
||||
FT_FREE( entry->string );
|
||||
|
||||
FT_FREE( table->langTags );
|
||||
}
|
||||
|
||||
table->numNameRecords = 0;
|
||||
table->numLangTagRecords = 0;
|
||||
table->format = 0;
|
||||
table->storageOffset = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue