[t1cid] Improve cid_get_cid_from_glyph_index().

Update cid_get_cid_from_glyph_index() to
return an error and CID=0 in the case that
the specified glyph index points to an invalid
entry.

cidgload.h (cid_compute_fd_and_offsets):
Declare new helper function to set the
fd_select and 2 offsets to access the glyph
description data.

cidgload.c (cid_compute_fd_and_offsets):
Move the part loading fd_select and 2 offsets
from cid_load_glyph() to here.  If the loaded
parameters are broken, return the Invalid_Offset
error.  This function does not load the glyph
data, only fills these parameters.

(cid_load_glyph): Use new helper function in above.

cidriver.c (cid_get_cid_from_glyph_index):
Check whether the requested glyph index points
to a valid entry, by calling cid_compute_fd_and_offsets().
If it is valid, fill the cid by the glyph
index (=CID).  If it is invalid, return an
error and fill the cid by 0.
This commit is contained in:
suzuki toshiya 2023-05-03 01:31:37 +00:00
parent 77bbfc5960
commit be15811c46
3 changed files with 128 additions and 59 deletions

View File

@ -40,6 +40,108 @@
#define FT_COMPONENT cidgload
/*
* A helper function to compute FD number (fd_select),
* the offset to the head of the glyph data (off1),
* and the offset to the and of the glyph data (off2).
*
* The number how many times cid_get_offset() is invoked
* can be controlled by the number how many non-NULL
* arguments are given. If fd_select is non-NULL but
* off1 and off2 are NULL, cid_get_offset() is invoked
* only for fd_select, off1/off2 are not validated.
*
*/
FT_LOCAL_DEF( FT_Error )
cid_compute_fd_and_offsets( CID_Face face,
FT_UInt glyph_index,
FT_ULong* fd_select_p,
FT_ULong* off1_p,
FT_ULong* off2_p )
{
FT_Error error = FT_Err_Ok;
CID_FaceInfo cid = &face->cid;
FT_Stream stream = face->cid_stream;
FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes;
FT_Byte* p;
FT_Bool need_frame_exit = 0;
FT_ULong fd_select, off1, off2;
/* For ordinary fonts read the CID font dictionary index */
/* and charstring offset from the CIDMap. */
if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset +
glyph_index * entry_len ) ||
FT_FRAME_ENTER( 2 * entry_len ) )
goto Exit;
need_frame_exit = 1;
p = (FT_Byte*)stream->cursor;
fd_select = cid_get_offset( &p, cid->fd_bytes );
off1 = cid_get_offset( &p, cid->gd_bytes );
p += cid->fd_bytes;
off2 = cid_get_offset( &p, cid->gd_bytes );
if (fd_select_p)
*fd_select_p = fd_select;
if (off1_p)
*off1_p = off1;
if (off2_p)
*off2_p = off2;
if ( fd_select >= cid->num_dicts )
{
/*
* fd_select == 0xFF is often used to indicate that the CID
* has no charstring to be rendered, similar to GID = 0xFFFF
* in TrueType fonts.
*/
if ( (cid->fd_bytes == 1 && fd_select == 0xFFU ) ||
(cid->fd_bytes == 2 && fd_select == 0xFFFFU ) )
{
FT_TRACE1(( "cid_load_glyph: fail for glyph_index=%d, "
"FD number %ld is the max integer fitting into %d byte%s\n",
glyph_index, fd_select, cid->fd_bytes,
cid->fd_bytes == 1 ? "" : "s" ));
}
else
{
FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
"FD number %ld > number of dicts %d\n",
glyph_index, fd_select, cid->num_dicts ));
}
error = FT_THROW( Invalid_Offset );
goto Exit;
}
else if ( off2 > stream->size )
{
FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
"end of the glyph data is beyond the data stream\n",
glyph_index ));
error = FT_THROW( Invalid_Offset );
goto Exit;
}
else if ( off1 > off2 )
{
FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
"the end position of glyph data is set before the start position\n",
glyph_index ));
error = FT_THROW( Invalid_Offset );
}
Exit:
if ( need_frame_exit )
FT_FRAME_EXIT();
return error;
}
FT_CALLBACK_DEF( FT_Error )
cid_load_glyph( T1_Decoder decoder,
FT_UInt glyph_index )
@ -97,68 +199,15 @@
else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
/* For ordinary fonts read the CID font dictionary index */
/* and charstring offset from the CIDMap. */
{
FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes;
FT_ULong off1, off2;
if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset +
glyph_index * entry_len ) ||
FT_FRAME_ENTER( 2 * entry_len ) )
error = cid_compute_fd_and_offsets( face, glyph_index,
&fd_select, &off1, &off2 );
if ( error )
goto Exit;
p = (FT_Byte*)stream->cursor;
fd_select = cid_get_offset( &p, cid->fd_bytes );
off1 = cid_get_offset( &p, cid->gd_bytes );
p += cid->fd_bytes;
off2 = cid_get_offset( &p, cid->gd_bytes );
FT_FRAME_EXIT();
if ( fd_select >= cid->num_dicts )
{
/*
* fd_select == 0xFF is often used to indicate that the CID
* has no charstring to be rendered, similar to GID = 0xFFFF
* in TrueType fonts.
*/
if ( (cid->fd_bytes == 1 && fd_select == 0xFFU ) ||
(cid->fd_bytes == 2 && fd_select == 0xFFFFU ) )
{
FT_TRACE1(( "cid_load_glyph: fail for glyph_index=%d, "
"FD number %ld is the max integer fitting into %d byte%s\n",
glyph_index, fd_select, cid->fd_bytes,
cid->fd_bytes == 1 ? "" : "s" ));
}
else
{
FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
"FD number %ld > number of dicts %d\n",
glyph_index, fd_select, cid->num_dicts ));
}
error = FT_THROW( Invalid_Offset );
goto Exit;
}
else if ( off2 > stream->size )
{
FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
"end of the glyph data is beyond the data stream\n",
glyph_index ));
error = FT_THROW( Invalid_Offset );
goto Exit;
}
else if ( off1 > off2 )
{
FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
"the end position of glyph data is set before the start position\n",
glyph_index ));
error = FT_THROW( Invalid_Offset );
goto Exit;
}
glyph_length = off2 - off1;
if ( glyph_length == 0 ||

View File

@ -42,6 +42,14 @@ FT_BEGIN_HEADER
FT_Int32 load_flags );
FT_LOCAL( FT_Error )
cid_compute_fd_and_offsets( CID_Face face,
FT_UInt glyph_index,
FT_ULong* fd_select_p,
FT_ULong* off1_p,
FT_ULong* off2_p );
FT_END_HEADER
#endif /* CIDGLOAD_H_ */

View File

@ -150,11 +150,23 @@
FT_UInt *cid )
{
FT_Error error = FT_Err_Ok;
FT_UNUSED( face );
if ( cid )
*cid = glyph_index; /* identity mapping */
/*
* Currently, FreeType does not support an incrementally-
* defined CID-keyed font that stores the glyph description
* data in /GlyphDirectory array or dictionary.
* Thus the font loaded by the incremental loading feature
* is not handled in here.
*/
error = cid_compute_fd_and_offsets( face, glyph_index,
NULL, NULL, NULL );
if ( error )
*cid = 0;
else
*cid = glyph_index;
return error;
}