* src/bdf/bdflib.c: various improvements to the bdf loader, mainly
used to reduce the amount of heap size required to only test wether
we're dealing with a BDF font (the old code allocated 64 Kb right
before any test).
* src/lzw/ftlzw.c (FT_Stream_OpenLZW): modified the function to check
the LZW header before doing anything else. This helps avoid un-necessary
heap allocations (400 Kb of heap memory for the LZW decoder ! Oh my !)
* src/gzip/ftgzip.c (FT_Stream_OpenGZip): ditto for the .gz decoder,
though the code savings is smaller.
diff --git a/src/bdf/bdflib.c b/src/bdf/bdflib.c
index 825385e..9ac50be 100644
--- a/src/bdf/bdflib.c
+++ b/src/bdf/bdflib.c
@@ -224,7 +224,6 @@
if ( FT_NEW_ARRAY( ht->table, ht->size ) )
goto Exit;
- FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * ht->size );
for ( i = 0, bp = obp; i < sz; i++, bp++ )
{
@@ -255,7 +254,6 @@
if ( FT_NEW_ARRAY( ht->table, sz ) )
goto Exit;
- FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * sz );
Exit:
return error;
@@ -351,6 +349,7 @@
char** field;
unsigned long size;
unsigned long used;
+ FT_Memory memory;
} _bdf_list_t;
@@ -389,20 +388,123 @@
#define sbitset( m, cc ) ( m[(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) )
+ static void
+ _bdf_list_init( _bdf_list_t* list,
+ FT_Memory memory )
+ {
+ FT_ZERO(list);
+ list->memory = memory;
+ }
+
+ static void
+ _bdf_list_done( _bdf_list_t* list )
+ {
+ FT_Memory memory = list->memory;
+
+ if ( memory )
+ {
+ FT_FREE( list->field );
+ FT_ZERO(list);
+ }
+ }
+
+
+ static FT_Error
+ _bdf_list_ensure( _bdf_list_t* list,
+ int num_items )
+ {
+ FT_Error error = 0;
+
+ if ( num_items > list->size )
+ {
+ int oldsize = list->size;
+ int newsize = oldsize + (oldsize >> 1) + 4;
+ int bigsize = FT_INT_MAX / sizeof(char*);
+ FT_Memory memory = list->memory;
+
+ if ( oldsize == bigsize )
+ {
+ error = FT_Err_Out_Of_Memory;
+ goto Exit;
+ }
+ else if ( newsize < oldsize || newsize > bigsize )
+ newsize = bigsize;
+
+ if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) )
+ goto Exit;
+
+ list->size = newsize;
+ }
+ Exit:
+ return error;
+ }
+
+
+ static void
+ _bdf_list_shift( _bdf_list_t* list,
+ unsigned long n )
+ {
+ unsigned long i, u;
+
+
+ if ( list == 0 || list->used == 0 || n == 0 )
+ return;
+
+ if ( n >= list->used )
+ {
+ list->used = 0;
+ return;
+ }
+
+ for ( u = n, i = 0; u < list->used; i++, u++ )
+ list->field[i] = list->field[u];
+ list->used -= n;
+ }
+
+
+ static char *
+ _bdf_list_join( _bdf_list_t* list,
+ int c,
+ unsigned long *alen )
+ {
+ unsigned long i, j;
+ char *fp, *dp;
+
+
+ *alen = 0;
+
+ if ( list == 0 || list->used == 0 )
+ return 0;
+
+ dp = list->field[0];
+ for ( i = j = 0; i < list->used; i++ )
+ {
+ fp = list->field[i];
+ while ( *fp )
+ dp[j++] = *fp++;
+
+ if ( i + 1 < list->used )
+ dp[j++] = (char)c;
+ }
+ dp[j] = 0;
+
+ *alen = j;
+ return dp;
+ }
+
+
+
/* An empty string for empty fields. */
static const char empty[1] = { 0 }; /* XXX eliminate this */
- /* Assume the line is NULL-terminated and that the `list' parameter */
- /* was initialized the first time it was used. */
static FT_Error
- _bdf_split( char* separators,
- char* line,
- unsigned long linelen,
- _bdf_list_t* list,
- FT_Memory memory )
+ _bdf_list_split( _bdf_list_t* list,
+ char* separators,
+ char* line,
+ unsigned long linelen )
{
int mult, final_empty;
char *sp, *ep, *end;
@@ -451,20 +553,9 @@
/* Resize the list if necessary. */
if ( list->used == list->size )
{
- if ( list->size == 0 )
- {
- if ( FT_NEW_ARRAY( list->field, 5 ) )
- goto Exit;
- }
- else
- {
- if ( FT_RENEW_ARRAY ( list->field ,
- list->size,
- list->size + 5 ) )
- goto Exit;
- }
-
- list->size += 5;
+ error = _bdf_list_ensure( list, list->used+1 );
+ if ( error )
+ goto Exit;
}
/* Assign the field appropriately. */
@@ -489,48 +580,16 @@
}
/* Finally, NULL-terminate the list. */
- if ( list->used + final_empty + 1 >= list->size )
+ if ( list->used + final_empty >= list->size )
{
- if ( list->used == list->size )
- {
- if ( list->size == 0 )
- {
- if ( FT_NEW_ARRAY( list->field, 5 ) )
- goto Exit;
- }
- else
- {
- if ( FT_RENEW_ARRAY( list->field,
- list->size,
- list->size + 5 ) )
- goto Exit;
- }
-
- list->size += 5;
- }
+ error = _bdf_list_ensure( list, list->used+final_empty+1 );
+ if ( error )
+ goto Exit;
}
if ( final_empty )
list->field[list->used++] = (char*)empty;
- if ( list->used == list->size )
- {
- if ( list->size == 0 )
- {
- if ( FT_NEW_ARRAY( list->field, 5 ) )
- goto Exit;
- }
- else
- {
- if ( FT_RENEW_ARRAY( list->field,
- list->size,
- list->size + 5 ) )
- goto Exit;
- }
-
- list->size += 5;
- }
-
list->field[list->used] = 0;
Exit:
@@ -538,100 +597,8 @@
}
- static void
- _bdf_shift( unsigned long n,
- _bdf_list_t* list )
- {
- unsigned long i, u;
-
- if ( list == 0 || list->used == 0 || n == 0 )
- return;
-
- if ( n >= list->used )
- {
- list->used = 0;
- return;
- }
-
- for ( u = n, i = 0; u < list->used; i++, u++ )
- list->field[i] = list->field[u];
- list->used -= n;
- }
-
-
- static char *
- _bdf_join( int c,
- unsigned long* len,
- _bdf_list_t* list )
- {
- unsigned long i, j;
- char *fp, *dp;
-
-
- if ( list == 0 || list->used == 0 )
- return 0;
-
- *len = 0;
-
- dp = list->field[0];
- for ( i = j = 0; i < list->used; i++ )
- {
- fp = list->field[i];
- while ( *fp )
- dp[j++] = *fp++;
-
- if ( i + 1 < list->used )
- dp[j++] = (char)c;
- }
- dp[j] = 0;
-
- *len = j;
- return dp;
- }
-
-
- /* High speed file reader that passes each line to a callback. */
- static FT_Error
- bdf_internal_readstream( FT_Stream stream,
- char* buffer,
- int count,
- int *read_bytes )
- {
- int rbytes;
- unsigned long pos = stream->pos;
- FT_Error error = BDF_Err_Ok;
-
-
- if ( pos > stream->size )
- {
- FT_ERROR(( "bdf_internal_readstream:" ));
- FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
- pos, stream->size ));
- error = BDF_Err_Invalid_Stream_Operation;
- goto Exit;
- }
-
- if ( stream->read )
- rbytes = stream->read( stream, pos,
- (unsigned char *)buffer, count );
- else
- {
- rbytes = stream->size - pos;
- if ( rbytes > count )
- rbytes = count;
-
- FT_MEM_COPY( buffer, stream->base + pos, rbytes );
- }
-
- stream->pos = pos + rbytes;
-
- *read_bytes = rbytes;
-
- Exit:
- return error;
- }
-
+#define NO_SKIP 256 /* this value cannot be stored in a 'char' */
static FT_Error
_bdf_readstream( FT_Stream stream,
@@ -640,10 +607,10 @@
unsigned long *lno )
{
_bdf_line_func_t cb;
- unsigned long lineno;
- int n, done, refill, bytes, hold;
- char *ls, *le, *pp, *pe, *hp;
- char *buf = 0;
+ unsigned long lineno, buf_size;
+ int refill, bytes, hold, to_skip;
+ int start, end, cursor, avail;
+ char* buf = 0;
FT_Memory memory = stream->memory;
FT_Error error = BDF_Err_Ok;
@@ -654,85 +621,115 @@
goto Exit;
}
- if ( FT_NEW_ARRAY( buf, 65536L ) )
+ /* initial size and allocation of the input buffer
+ */
+ buf_size = 1024;
+
+ if ( FT_NEW_ARRAY( buf, buf_size ) )
goto Exit;
- cb = callback;
- lineno = 1;
- buf[0] = 0;
+ cb = callback;
+ lineno = 1;
+ buf[0] = 0;
+ start = 0;
+ end = 0;
+ avail = 0;
+ cursor = 0;
+ refill = 1;
+ to_skip = NO_SKIP;
- done = 0;
- pp = ls = le = buf;
-
- bytes = 65536L;
-
- while ( !done )
+ for (;;)
{
- error = bdf_internal_readstream( stream, pp, bytes, &n );
- if ( error )
- goto Exit;
-
- if ( n == 0 )
- break;
-
- /* Determine the new end of the buffer pages. */
- pe = pp + n;
-
- for ( refill = 0; done == 0 && refill == 0; )
+ if ( refill )
{
- while ( le < pe && *le != '\n' && *le != '\r' )
- le++;
+ bytes = (int) FT_Stream_TryRead( stream, buf + cursor,
+ (FT_ULong)(buf_size - cursor) );
+ avail = cursor + bytes;
+ cursor = 0;
+ refill = 0;
+ }
- if ( le == pe )
+ end = start;
+
+ /* should we skip an optional character like \n or \r ? */
+ if ( start < avail && buf[start] == to_skip )
+ {
+ start += 1;
+ to_skip = NO_SKIP;
+ continue;
+ }
+
+ /* try to find the end of the line */
+ while ( end < avail && buf[end] != '\n' && buf[end] != '\r' )
+ end++;
+
+ /* if we hit the end of the buffer, try shifting its content
+ * or even resizing it
+ */
+ if ( end >= avail )
+ {
+ if ( bytes == 0 ) /* last line in file doesn't end in \r or \n */
+ break; /* ignore it then exit */
+
+ if ( start == 0 )
{
- /* Hit the end of the last page in the buffer. Need to find */
- /* out how many pages to shift and how many pages need to be */
- /* read in. Adjust the line start and end pointers down to */
- /* point to the right places in the pages. */
+ /* this line is definitely too long, try resizing the input buffer
+ * a bit to handle it.
+ */
+ FT_ULong new_size;
- pp = buf + ( ( ( ls - buf ) >> 13 ) << 13 );
- n = pp - buf;
- ls -= n;
- le -= n;
- n = pe - pp;
+ if ( buf_size >= 65536UL ) /* limit ourselves to 64 Kb */
+ {
+ error = BDF_Err_Invalid_Argument;
+ goto Exit;
+ }
- FT_MEM_MOVE( buf, pp, n );
+ new_size = buf_size*2;
+ if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) )
+ goto Exit;
- pp = buf + n;
- bytes = 65536L - n;
- refill = 1;
+ cursor = buf_size;
+ buf_size = new_size;
}
else
{
- /* Temporarily NULL-terminate the line. */
- hp = le;
- hold = *le;
- *le = 0;
+ bytes = avail - start;
- /* XXX: Use encoding independent value for 0x1a */
- if ( *ls != '#' && *ls != 0x1a &&
- le > ls &&
- ( error = (*cb)( ls, le - ls, lineno, (void *)&cb,
- client_data ) ) != BDF_Err_Ok )
- done = 1;
- else
- {
- ls = ++le;
- /* Handle the case of DOS crlf sequences. */
- if ( le < pe && hold == '\n' && *le =='\r' )
- ls = ++le;
- }
+ FT_MEM_COPY( buf, buf+start, bytes );
- /* Increment the line number. */
- lineno++;
-
- /* Restore the character at the end of the line. */
- *hp = (char)hold;
+ cursor = bytes;
+ avail -= bytes;
+ start = 0;
}
+ refill = 1;
+ continue;
}
+
+ /* Temporarily NUL-terminate the line. */
+ hold = buf[end];
+ buf[end] = 0;
+
+ /* XXX: Use encoding independent value for 0x1a */
+ if ( buf[start] != '#' && buf[start] != 0x1a && end > start )
+ {
+ error = (*cb)( buf+start, end-start, lineno, (void*)&cb, client_data );
+ if ( error )
+ break;
+ }
+
+ lineno += 1;
+ buf[end] = (char)hold;
+ start = end+1;
+
+ if ( hold == '\n' )
+ to_skip = '\r';
+ else if ( hold == '\r' )
+ to_skip = '\n';
+ else
+ to_skip = NO_SKIP;
}
- *lno = lineno;
+ *lno = lineno;
Exit:
FT_FREE( buf );
@@ -955,7 +952,8 @@
if ( c1->encoding < c2->encoding )
return -1;
- else if ( c1->encoding > c2->encoding )
+
+ if ( c1->encoding > c2->encoding )
return 1;
return 0;
@@ -979,23 +977,16 @@
if ( hash_lookup( name, &(font->proptbl) ) )
goto Exit;
- if ( font->nuser_props == 0 )
- {
- if ( FT_NEW_ARRAY( font->user_props, 1 ) )
- goto Exit;
- }
- else
- {
- if ( FT_RENEW_ARRAY( font->user_props,
- font->nuser_props,
- font->nuser_props + 1 ) )
- goto Exit;
- }
+ if ( FT_RENEW_ARRAY( font->user_props,
+ font->nuser_props,
+ font->nuser_props + 1 ) )
+ goto Exit;
p = font->user_props + font->nuser_props;
- FT_MEM_ZERO( p, sizeof ( bdf_property_t ) );
+ FT_ZERO( p );
n = (unsigned long)( ft_strlen( name ) + 1 );
+
if ( FT_NEW_ARRAY( p->name, n ) )
goto Exit;
@@ -1110,23 +1101,16 @@
FT_Error error = BDF_Err_Ok;
- if ( font->comments_len == 0 )
- {
- if ( FT_NEW_ARRAY( font->comments, len + 1 ) )
- goto Exit;
- }
- else
- {
- if ( FT_RENEW_ARRAY( font->comments,
- font->comments_len,
- font->comments_len + len + 1 ) )
- goto Exit;
- }
+ if ( FT_RENEW_ARRAY( font->comments,
+ font->comments_len,
+ font->comments_len + len + 1 ) )
+ goto Exit;
cp = font->comments + font->comments_len;
+
FT_MEM_COPY( cp, comment, len );
- cp += len;
- *cp++ = '\n';
+ cp[len] = '\n';
+
font->comments_len += len + 1;
Exit:
@@ -1155,16 +1139,16 @@
memory = font->memory;
+ _bdf_list_init( &list, memory );
+
font->spacing = opts->font_spacing;
len = (unsigned long)( ft_strlen( font->name ) + 1 );
FT_MEM_COPY( name, font->name, len );
- list.size = list.used = 0;
-
- error = _bdf_split( (char *)"-", name, len, &list, memory );
+ error = _bdf_list_split( &list, (char *)"-", name, len );
if ( error )
- goto Exit;
+ goto Fail;
if ( list.used == 15 )
{
@@ -1185,7 +1169,8 @@
}
}
- FT_FREE( list.field );
+ Fail:
+ _bdf_list_done( &list );
Exit:
return error;
@@ -1484,7 +1469,7 @@
goto Exit;
}
- error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 );
@@ -1538,15 +1523,17 @@
/* encoding can be checked for an unencoded character. */
FT_FREE( p->glyph_name );
- error = _bdf_split( (char *)" +", line, linelen, &p->list,memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
- _bdf_shift( 1, &p->list );
- s = _bdf_join( ' ', &slen, &p->list );
+ _bdf_list_shift( &p->list, 1 );
+
+ s = _bdf_list_join( &p->list, ' ', &slen );
if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )
goto Exit;
+
FT_MEM_COPY( p->glyph_name, s, slen + 1 );
p->flags |= _BDF_GLYPH;
@@ -1565,9 +1552,10 @@
goto Exit;
}
- error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
+
p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 );
/* Check to see whether this encoding has already been encountered. */
@@ -1598,8 +1586,7 @@
font->glyphs_size,
font->glyphs_size + 64 ) )
goto Exit;
- FT_MEM_ZERO( font->glyphs + font->glyphs_size,
- sizeof ( bdf_glyph_t ) * 64 ); /* FZ inutile */
+
font->glyphs_size += 64;
}
@@ -1619,18 +1606,11 @@
/* Allocate the next unencoded glyph. */
if ( font->unencoded_used == font->unencoded_size )
{
- if ( font->unencoded_size == 0 )
- {
- if ( FT_NEW_ARRAY( font->unencoded, 4 ) )
- goto Exit;
- }
- else
- {
- if ( FT_RENEW_ARRAY( font->unencoded ,
- font->unencoded_size,
- font->unencoded_size + 4 ) )
- goto Exit;
- }
+ if ( FT_RENEW_ARRAY( font->unencoded ,
+ font->unencoded_size,
+ font->unencoded_size + 4 ) )
+ goto Exit;
+
font->unencoded_size += 4;
}
@@ -1719,9 +1699,10 @@
goto Exit;
}
- error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
+
glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
p->flags |= _BDF_SWIDTH;
@@ -1731,9 +1712,10 @@
/* Expect the DWIDTH (scalable width) field next. */
if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 )
{
- error = _bdf_split( (char *)" +", line, linelen, &p->list,memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
+
glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 );
if ( !( p->flags & _BDF_SWIDTH ) )
@@ -1755,7 +1737,7 @@
/* Expect the BBX field next. */
if ( ft_memcmp( line, "BBX", 3 ) == 0 )
{
- error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
@@ -1936,13 +1918,13 @@
}
else
{
- error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
name = p->list.field[0];
- _bdf_shift( 1, &p->list );
- value = _bdf_join( ' ', &vlen, &p->list );
+ _bdf_list_shift( &p->list, 1 );
+ value = _bdf_list_join( &p->list, ' ', &vlen );
error = _bdf_add_property( p->font, name, value );
if ( error )
@@ -2057,7 +2039,7 @@
/* Check for the start of the properties. */
if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 )
{
- error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 );
@@ -2082,7 +2064,7 @@
goto Exit;
}
- error = _bdf_split( (char *)" +", line, linelen, &p->list , memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
@@ -2105,12 +2087,12 @@
/* The next thing to check for is the FONT field. */
if ( ft_memcmp( line, "FONT", 4 ) == 0 )
{
- error = _bdf_split( (char *)" +", line, linelen, &p->list , memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
- _bdf_shift( 1, &p->list );
+ _bdf_list_shift( &p->list, 1 );
- s = _bdf_join( ' ', &slen, &p->list );
+ s = _bdf_list_join( &p->list, ' ', &slen );
if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) )
goto Exit;
FT_MEM_COPY( p->font->name, s, slen + 1 );
@@ -2137,7 +2119,7 @@
goto Exit;
}
- error = _bdf_split( (char *)" +", line, linelen, &p->list, memory );
+ error = _bdf_list_split( &p->list, (char *)" +", line, linelen );
if ( error )
goto Exit;
@@ -2207,7 +2189,7 @@
FT_Error error = BDF_Err_Ok;
- if ( FT_ALLOC( p, sizeof ( _bdf_parse_t ) ) )
+ if ( FT_NEW( p ) )
goto Exit;
memory = NULL;
@@ -2215,6 +2197,8 @@
p->minlb = 32767;
p->memory = extmemory; /* only during font creation */
+ _bdf_list_init( &p->list, extmemory );
+
error = _bdf_readstream( stream, _bdf_parse_start,
(void *)p, &lineno );
if ( error )
@@ -2301,10 +2285,6 @@
}
}
- /* Free up the list used during the parsing. */
- if ( memory != NULL )
- FT_FREE( p->list.field );
-
if ( p->font != 0 )
{
/* Make sure the comments are NULL terminated if they exist. */
@@ -2327,7 +2307,10 @@
Exit:
if ( p )
{
+ _bdf_list_done( &p->list );
+
memory = extmemory;
+
FT_FREE( p );
}