ref: 5dbdb6c3c4f681186716234c3738cd3a0d2412a1
parent: 82dba7620e74d2245e576e61ef83f54c7c8f43dd
author: David Turner <[email protected]>
date: Fri Jan 5 08:14:08 EST 2007
* 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
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,10 @@
2007-01-04 David Turner <[email protected]>
- * 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 <[email protected]>
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -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;
+ }
}
}
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -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,56 +248,37 @@
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 ) ||
- FT_FRAME_ENTER( data_size ) )
+ idx->data_offset = idx->start + 3 + size;
+
+ if ( FT_STREAM_SKIP( size - offsize ) )
goto Exit;
- poff = idx->offsets;
- p = (FT_Byte*)stream->cursor;
- p_end = p + data_size;
+ size = cff_index_read_offset( idx, &error );
+ if (error)
+ goto Exit;
- switch ( offsize )
+ if ( size == 0 )
{
- case 1:
- for ( ; p < p_end; p++, poff++ )
- poff[0] = p[0];
- break;
-
- case 2:
- for ( ; p < p_end; p += 2, poff++ )
- poff[0] = FT_PEEK_USHORT( p );
- break;
-
- case 3:
- for ( ; p < p_end; p += 3, poff++ )
- poff[0] = FT_PEEK_OFF3( p );
- break;
-
- default:
- for ( ; p < p_end; p += 4, poff++ )
- poff[0] = FT_PEEK_ULONG( p );
+ error = CFF_Err_Invalid_Table;
+ goto Exit;
}
- FT_FRAME_EXIT();
+ idx->data_size = --size;
- idx->data_offset = FT_STREAM_POS();
- data_size = poff[-1] - 1;
-
if ( load )
{
/* load the data */
- if ( FT_FRAME_EXTRACT( data_size, idx->bytes ) )
+ if ( FT_FRAME_EXTRACT( size, idx->bytes ) )
goto Exit;
}
else
{
/* skip the data */
- if ( FT_STREAM_SKIP( data_size ) )
+ if ( FT_STREAM_SKIP( size ) )
goto Exit;
}
}
@@ -291,7 +292,7 @@
static void
- cff_done_index( CFF_Index idx )
+ cff_index_done( CFF_Index idx )
{
if ( idx->stream )
{
@@ -308,6 +309,67 @@
}
+ 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;
+
+ poff = idx->offsets;
+ p = (FT_Byte*)stream->cursor;
+ p_end = p + data_size;
+
+ switch ( offsize )
+ {
+ case 1:
+ for ( ; p < p_end; p++, poff++ )
+ poff[0] = p[0];
+ break;
+
+ case 2:
+ for ( ; p < p_end; p += 2, poff++ )
+ poff[0] = FT_PEEK_USHORT( p );
+ break;
+
+ case 3:
+ for ( ; p < p_end; p += 3, poff++ )
+ poff[0] = FT_PEEK_OFF3( p );
+ break;
+
+ default:
+ for ( ; p < p_end; p += 4, poff++ )
+ poff[0] = FT_PEEK_ULONG( p );
+ }
+
+ FT_FRAME_EXIT();
+ }
+
+ Exit:
+ if (error)
+ FT_FREE( idx->offsets );
+
+ return error;
+ }
+
+
+
+
/* allocate a table containing pointers to an index's elements */
static FT_Error
cff_index_get_pointers( CFF_Index idx,
@@ -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,23 +427,45 @@
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
- {
- element++;
- off2 = idx->offsets[element];
+ FT_ULong pos = element*idx->off_size;
- } while ( off2 == 0 && element < idx->count );
+ if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
+ goto Exit;
- if ( !off2 )
- off1 = 0;
+ off1 = cff_index_read_offset( idx, &error );
+ if (error) goto Exit;
+
+ if ( off1 != 0 )
+ {
+ 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 );
+ }
+ }
+
/* access element */
if ( off1 && off2 > off1 )
{
@@ -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 */
--- a/src/cff/cffload.h
+++ b/src/cff/cffload.h
@@ -52,6 +52,10 @@
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,
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -39,6 +39,9 @@
/* <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 @@
/* 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_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;