* src/cff/cffload.c, src/cff/cffload.h, src/cff/cffgload.c,
src/cff/cfftypes.h: formatting + do not load the CFF index offsets into memory, since this wastes a *lot* of heap memory with large Asian CFF fonts. There is no significant performance loss
This commit is contained in:
parent
82dba7620e
commit
5dbdb6c3c4
@ -1,6 +1,10 @@
|
||||
2007-01-04 David Turner <david@freetype.org>
|
||||
|
||||
* src/cff/cffload.c: formatting
|
||||
* src/cff/cffload.c, src/cff/cffload.h, src/cff/cffgload.c,
|
||||
src/cff/cfftypes.h: formatting + do not load the CFF index
|
||||
offsets into memory, since this wastes a *lot* of heap memory
|
||||
with large Asian CFF fonts. There is no significant performance
|
||||
loss
|
||||
|
||||
2007-01-04 David Turner <david@freetype.org>
|
||||
|
||||
|
@ -2291,9 +2291,8 @@
|
||||
if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
|
||||
cff->charset.cids )
|
||||
{
|
||||
if ( glyph_index < cff->charset.max_cid )
|
||||
glyph_index = cff->charset.cids[glyph_index];
|
||||
else
|
||||
glyph_index = cff_charset_cid_to_gindex( &cff->charset, glyph_index );
|
||||
if ( glyph_index == 0 )
|
||||
return CFF_Err_Invalid_Argument;
|
||||
}
|
||||
else if ( glyph_index >= cff->num_glyphs )
|
||||
@ -2423,13 +2422,13 @@
|
||||
/* See how charstring loads at cff_index_access_element() in */
|
||||
/* cffload.c. */
|
||||
{
|
||||
CFF_IndexRec csindex = cff->charstrings_index;
|
||||
CFF_Index csindex = &cff->charstrings_index;
|
||||
|
||||
|
||||
glyph->root.control_data =
|
||||
csindex.bytes + csindex.offsets[glyph_index] - 1;
|
||||
glyph->root.control_len =
|
||||
charstring_len;
|
||||
if (csindex->offsets)
|
||||
{
|
||||
glyph->root.control_data = csindex->bytes + csindex->offsets[glyph_index] - 1;
|
||||
glyph->root.control_len = charstring_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,11 +193,33 @@
|
||||
#undef FT_COMPONENT
|
||||
#define FT_COMPONENT trace_cffload
|
||||
|
||||
/* read an offset from the index's stream current position */
|
||||
static FT_ULong
|
||||
cff_index_read_offset( CFF_Index idx,
|
||||
FT_Error *perror )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Stream stream = idx->stream;
|
||||
FT_Byte tmp[4];
|
||||
FT_ULong result = 0;
|
||||
|
||||
if ( !FT_STREAM_READ( tmp, idx->off_size ) )
|
||||
{
|
||||
FT_Int nn;
|
||||
|
||||
for ( nn = 0; nn < idx->off_size; nn++ )
|
||||
result = (result << 8) | tmp[nn];
|
||||
}
|
||||
|
||||
*perror = error;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static FT_Error
|
||||
cff_new_index( CFF_Index idx,
|
||||
FT_Stream stream,
|
||||
FT_Bool load )
|
||||
cff_index_init( CFF_Index idx,
|
||||
FT_Stream stream,
|
||||
FT_Bool load )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Memory memory = stream->memory;
|
||||
@ -207,14 +229,12 @@
|
||||
FT_MEM_ZERO( idx, sizeof ( *idx ) );
|
||||
|
||||
idx->stream = stream;
|
||||
idx->start = FT_STREAM_POS();
|
||||
if ( !FT_READ_USHORT( count ) &&
|
||||
count > 0 )
|
||||
{
|
||||
FT_Byte* p;
|
||||
FT_Byte offsize;
|
||||
FT_ULong data_size;
|
||||
FT_ULong* poff;
|
||||
FT_Byte* p_end;
|
||||
FT_ULong size, last_offset;
|
||||
|
||||
|
||||
/* there is at least one element; read the offset size, */
|
||||
@ -228,12 +248,86 @@
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
idx->stream = stream;
|
||||
idx->count = count;
|
||||
idx->off_size = offsize;
|
||||
data_size = (FT_ULong)( count + 1 ) * offsize;
|
||||
size = (FT_ULong)( count + 1 ) * offsize;
|
||||
|
||||
if ( FT_NEW_ARRAY( idx->offsets, count + 1 ) ||
|
||||
idx->data_offset = idx->start + 3 + size;
|
||||
|
||||
if ( FT_STREAM_SKIP( size - offsize ) )
|
||||
goto Exit;
|
||||
|
||||
size = cff_index_read_offset( idx, &error );
|
||||
if (error)
|
||||
goto Exit;
|
||||
|
||||
if ( size == 0 )
|
||||
{
|
||||
error = CFF_Err_Invalid_Table;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
idx->data_size = --size;
|
||||
|
||||
if ( load )
|
||||
{
|
||||
/* load the data */
|
||||
if ( FT_FRAME_EXTRACT( size, idx->bytes ) )
|
||||
goto Exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip the data */
|
||||
if ( FT_STREAM_SKIP( size ) )
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
if ( error )
|
||||
FT_FREE( idx->offsets );
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cff_index_done( CFF_Index idx )
|
||||
{
|
||||
if ( idx->stream )
|
||||
{
|
||||
FT_Stream stream = idx->stream;
|
||||
FT_Memory memory = stream->memory;
|
||||
|
||||
|
||||
if ( idx->bytes )
|
||||
FT_FRAME_RELEASE( idx->bytes );
|
||||
|
||||
FT_FREE( idx->offsets );
|
||||
FT_MEM_ZERO( idx, sizeof ( *idx ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static FT_Error
|
||||
cff_index_load_offsets( CFF_Index idx )
|
||||
{
|
||||
FT_Error error = 0;
|
||||
FT_Stream stream = idx->stream;
|
||||
FT_Memory memory = stream->memory;
|
||||
|
||||
if ( idx->count > 0 && idx->offsets == NULL )
|
||||
{
|
||||
FT_Byte offsize = idx->off_size;
|
||||
FT_ULong data_size;
|
||||
FT_Byte* p;
|
||||
FT_Byte* p_end;
|
||||
FT_ULong* poff;
|
||||
|
||||
data_size = (FT_ULong)( idx->count + 1 ) * offsize;
|
||||
|
||||
if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
|
||||
FT_STREAM_SEEK( idx->start + 3 ) ||
|
||||
FT_FRAME_ENTER( data_size ) )
|
||||
goto Exit;
|
||||
|
||||
@ -264,48 +358,16 @@
|
||||
}
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
idx->data_offset = FT_STREAM_POS();
|
||||
data_size = poff[-1] - 1;
|
||||
|
||||
if ( load )
|
||||
{
|
||||
/* load the data */
|
||||
if ( FT_FRAME_EXTRACT( data_size, idx->bytes ) )
|
||||
goto Exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip the data */
|
||||
if ( FT_STREAM_SKIP( data_size ) )
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
if ( error )
|
||||
if (error)
|
||||
FT_FREE( idx->offsets );
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cff_done_index( CFF_Index idx )
|
||||
{
|
||||
if ( idx->stream )
|
||||
{
|
||||
FT_Stream stream = idx->stream;
|
||||
FT_Memory memory = stream->memory;
|
||||
|
||||
|
||||
if ( idx->bytes )
|
||||
FT_FRAME_RELEASE( idx->bytes );
|
||||
|
||||
FT_FREE( idx->offsets );
|
||||
FT_MEM_ZERO( idx, sizeof ( *idx ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* allocate a table containing pointers to an index's elements */
|
||||
@ -321,6 +383,13 @@
|
||||
|
||||
*table = 0;
|
||||
|
||||
if ( idx->offsets == NULL )
|
||||
{
|
||||
error = cff_index_load_offsets( idx );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) )
|
||||
{
|
||||
old_offset = 1;
|
||||
@ -330,6 +399,10 @@
|
||||
if ( !offset )
|
||||
offset = old_offset;
|
||||
|
||||
/* sanity check for invalid offset tables */
|
||||
else if ( offset < old_offset || offset-1 >= idx->data_size )
|
||||
offset = old_offset;
|
||||
|
||||
t[n] = idx->bytes + offset - 1;
|
||||
|
||||
old_offset = offset;
|
||||
@ -337,6 +410,7 @@
|
||||
*table = t;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -353,21 +427,43 @@
|
||||
if ( idx && idx->count > element )
|
||||
{
|
||||
/* compute start and end offsets */
|
||||
FT_ULong off1, off2 = 0;
|
||||
FT_Stream stream = idx->stream;
|
||||
FT_ULong off1, off2 = 0;
|
||||
|
||||
|
||||
off1 = idx->offsets[element];
|
||||
if ( off1 )
|
||||
/* load offsets from file or the offset table */
|
||||
if ( !idx->offsets )
|
||||
{
|
||||
do
|
||||
FT_ULong pos = element*idx->off_size;
|
||||
|
||||
if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
|
||||
goto Exit;
|
||||
|
||||
off1 = cff_index_read_offset( idx, &error );
|
||||
if (error) goto Exit;
|
||||
|
||||
if ( off1 != 0 )
|
||||
{
|
||||
element++;
|
||||
off2 = idx->offsets[element];
|
||||
do
|
||||
{
|
||||
element++;
|
||||
off2 = cff_index_read_offset( idx, &error );
|
||||
}
|
||||
while ( off2 == 0 && element < idx->count );
|
||||
}
|
||||
}
|
||||
else /* use offsets table */
|
||||
{
|
||||
off1 = idx->offsets[element];
|
||||
if ( off1 )
|
||||
{
|
||||
do
|
||||
{
|
||||
element++;
|
||||
off2 = idx->offsets[element];
|
||||
|
||||
} while ( off2 == 0 && element < idx->count );
|
||||
|
||||
if ( !off2 )
|
||||
off1 = 0;
|
||||
} while ( off2 == 0 && element < idx->count );
|
||||
}
|
||||
}
|
||||
|
||||
/* access element */
|
||||
@ -383,9 +479,6 @@
|
||||
else
|
||||
{
|
||||
/* this index is still on disk/file, access it through a frame */
|
||||
FT_Stream stream = idx->stream;
|
||||
|
||||
|
||||
if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
|
||||
FT_FRAME_EXTRACT( off2 - off1, *pbytes ) )
|
||||
goto Exit;
|
||||
@ -660,6 +753,18 @@
|
||||
}
|
||||
|
||||
|
||||
FT_LOCAL_DEF( FT_UInt )
|
||||
cff_charset_cid_to_gindex( CFF_Charset charset,
|
||||
FT_UInt cid )
|
||||
{
|
||||
FT_UInt result = 0;
|
||||
|
||||
if ( cid < charset->max_cid )
|
||||
result = charset->cids[cid];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cff_charset_free_cids( CFF_Charset charset,
|
||||
FT_Memory memory )
|
||||
@ -1209,7 +1314,7 @@
|
||||
priv->local_subrs_offset ) )
|
||||
goto Exit;
|
||||
|
||||
error = cff_new_index( &font->local_subrs_index, stream, 1 );
|
||||
error = cff_index_init( &font->local_subrs_index, stream, 1 );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
@ -1231,7 +1336,7 @@
|
||||
{
|
||||
if ( subfont )
|
||||
{
|
||||
cff_done_index( &subfont->local_subrs_index );
|
||||
cff_index_done( &subfont->local_subrs_index );
|
||||
FT_FREE( subfont->local_subrs );
|
||||
}
|
||||
}
|
||||
@ -1287,10 +1392,10 @@
|
||||
goto Exit;
|
||||
|
||||
/* read the name, top dict, string and global subrs index */
|
||||
if ( FT_SET_ERROR( cff_new_index( &font->name_index, stream, 0 )) ||
|
||||
FT_SET_ERROR( cff_new_index( &font->font_dict_index, stream, 0 )) ||
|
||||
FT_SET_ERROR( cff_new_index( &font->string_index, stream, 0 )) ||
|
||||
FT_SET_ERROR( cff_new_index( &font->global_subrs_index, stream, 1 )) )
|
||||
if ( FT_SET_ERROR( cff_index_init( &font->name_index, stream, 0 )) ||
|
||||
FT_SET_ERROR( cff_index_init( &font->font_dict_index, stream, 0 )) ||
|
||||
FT_SET_ERROR( cff_index_init( &font->string_index, stream, 0 )) ||
|
||||
FT_SET_ERROR( cff_index_init( &font->global_subrs_index, stream, 1 )) )
|
||||
goto Exit;
|
||||
|
||||
/* well, we don't really forget the `disabled' fonts... */
|
||||
@ -1318,7 +1423,7 @@
|
||||
if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
|
||||
goto Exit;
|
||||
|
||||
error = cff_new_index( &font->charstrings_index, stream, 0 );
|
||||
error = cff_index_init( &font->charstrings_index, stream, 0 );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
@ -1335,7 +1440,7 @@
|
||||
if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
|
||||
goto Exit;
|
||||
|
||||
error = cff_new_index( &fd_index, stream, 0 );
|
||||
error = cff_index_init( &fd_index, stream, 0 );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
@ -1371,7 +1476,7 @@
|
||||
base_offset + dict->cid_fd_select_offset );
|
||||
|
||||
Fail_CID:
|
||||
cff_done_index( &fd_index );
|
||||
cff_index_done( &fd_index );
|
||||
|
||||
if ( error )
|
||||
goto Exit;
|
||||
@ -1441,11 +1546,11 @@
|
||||
FT_UInt idx;
|
||||
|
||||
|
||||
cff_done_index( &font->global_subrs_index );
|
||||
cff_done_index( &font->string_index );
|
||||
cff_done_index( &font->font_dict_index );
|
||||
cff_done_index( &font->name_index );
|
||||
cff_done_index( &font->charstrings_index );
|
||||
cff_index_done( &font->global_subrs_index );
|
||||
cff_index_done( &font->string_index );
|
||||
cff_index_done( &font->font_dict_index );
|
||||
cff_index_done( &font->name_index );
|
||||
cff_index_done( &font->charstrings_index );
|
||||
|
||||
/* release font dictionaries, but only if working with */
|
||||
/* a CID keyed CFF font */
|
||||
|
@ -52,6 +52,10 @@ FT_BEGIN_HEADER
|
||||
FT_Byte** pbytes );
|
||||
|
||||
|
||||
FT_LOCAL( FT_UInt )
|
||||
cff_charset_cid_to_gindex( CFF_Charset charset,
|
||||
FT_UInt cid );
|
||||
|
||||
FT_LOCAL( FT_Error )
|
||||
cff_font_load( FT_Stream stream,
|
||||
FT_Int face_index,
|
||||
|
@ -39,6 +39,9 @@ FT_BEGIN_HEADER
|
||||
/* <Fields> */
|
||||
/* stream :: The source input stream. */
|
||||
/* */
|
||||
/* start :: The position of the first index byte in the */
|
||||
/* input stream */
|
||||
/* */
|
||||
/* count :: The number of elements in the index. */
|
||||
/* */
|
||||
/* off_size :: The size in bytes of object offsets in index. */
|
||||
@ -46,16 +49,21 @@ FT_BEGIN_HEADER
|
||||
/* data_offset :: The position of first data byte in the index's */
|
||||
/* bytes. */
|
||||
/* */
|
||||
/* offsets :: A table of element offsets in the index. */
|
||||
/* data_size :: size of data table in this index */
|
||||
/* */
|
||||
/* offsets :: A table of element offsets in the index. must be */
|
||||
/* loaded explicitely */
|
||||
/* */
|
||||
/* bytes :: If the index is loaded in memory, its bytes. */
|
||||
/* */
|
||||
typedef struct CFF_IndexRec_
|
||||
{
|
||||
FT_Stream stream;
|
||||
FT_ULong start;
|
||||
FT_UInt count;
|
||||
FT_Byte off_size;
|
||||
FT_ULong data_offset;
|
||||
FT_ULong data_size;
|
||||
|
||||
FT_ULong* offsets;
|
||||
FT_Byte* bytes;
|
||||
@ -85,6 +93,8 @@ FT_BEGIN_HEADER
|
||||
FT_UShort* cids; /* the inverse mapping of `sids'; only needed */
|
||||
/* for CID-keyed fonts */
|
||||
FT_UInt max_cid;
|
||||
FT_UInt num_glyphs;
|
||||
|
||||
} CFF_CharsetRec, *CFF_Charset;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user