From 29873a0ccd69376125323ded561e271872564077 Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 23 Oct 2006 10:23:17 +0000 Subject: [PATCH] * src/sfnt/ttmtx.c, src/cff/cffload.c: speeding up the CFF font loader, with some large CFF fonts, FT_Open_Face is now 350% faster ! --- ChangeLog | 8 ++- src/cff/cffload.c | 158 ++++++++++++++++++++++++++-------------------- src/sfnt/ttmtx.c | 19 +++--- 3 files changed, 108 insertions(+), 77 deletions(-) diff --git a/ChangeLog b/ChangeLog index ac3167d9b..20b7bacd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,10 @@ 2006-10-23 David Turner - * src/pshinter/pshalgo.c: major speed improvements to the Postscript - hinter, more than 100% speed increase on my machine + * src/sfnt/ttmtx.c, src/cff/cffload.c: speeding up the CFF font + loader, with some large CFF fonts, FT_Open_Face is now 350% faster ! + + * src/pshinter/pshalgo.c: major speed improvements to the Postscript + hinter, more than 100% speed increase on my machine 2006-10-15 suzuki toshiya @@ -115,6 +118,7 @@ * src/smooth/ftsmooth.c (ft_smooth_render_generic): Remove arguments `hmul' and `vmul'. + 5A Handle subpixel rendering. Simplify function. (ft_smooth_render_lcd): Use `FT_RENDER_MODE_LCD'. diff --git a/src/cff/cffload.c b/src/cff/cffload.c index ac5ed85b4..6abd9ea5f 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1063,24 +1063,6 @@ #define FT_COMPONENT trace_cffload - /* read a CFF offset from memory */ - static FT_ULong - cff_get_offset( FT_Byte* p, - FT_Byte off_size ) - { - FT_ULong result; - - - for ( result = 0; off_size > 0; off_size-- ) - { - result <<= 8; - result |= *p++; - } - - return result; - } - - static FT_Error cff_new_index( CFF_Index idx, FT_Stream stream, @@ -1101,6 +1083,7 @@ FT_Byte offsize; FT_ULong data_size; FT_ULong* poff; + FT_Byte* p_end; /* there is at least one element; read the offset size, */ @@ -1108,6 +1091,12 @@ if ( FT_READ_BYTE( offsize ) ) goto Exit; + if ( offsize < 1 || offsize > 4 ) + { + error = FT_Err_Invalid_Table; + goto Exit; + } + idx->stream = stream; idx->count = count; idx->off_size = offsize; @@ -1117,14 +1106,30 @@ FT_FRAME_ENTER( data_size ) ) goto Exit; - poff = idx->offsets; - p = (FT_Byte*)stream->cursor; + poff = idx->offsets; + p = (FT_Byte*)stream->cursor; + p_end = p + data_size; - for ( ; (FT_Short)count >= 0; count-- ) + switch ( offsize ) { - poff[0] = cff_get_offset( p, offsize ); - poff++; - p += 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(); @@ -1493,20 +1498,60 @@ /*************************************************************************/ /*************************************************************************/ + static FT_Error + cff_charset_compute_cids( CFF_Charset charset, + FT_UInt num_glyphs, + FT_Memory memory ) + { + FT_Error error = 0; + FT_UInt i; + FT_UShort max_cid = 0; + + if ( charset->max_cid > 0 ) + goto Exit; + + for ( i = 0; i < num_glyphs; i++ ) + if ( charset->sids[i] > max_cid ) + max_cid = charset->sids[i]; + max_cid++; + + if ( FT_NEW_ARRAY( charset->cids, max_cid ) ) + goto Exit; + + for ( i = 0; i < num_glyphs; i++ ) + charset->cids[charset->sids[i]] = (FT_UShort)i; + + charset->max_cid = max_cid; + + Exit: + return error; + } + + + static void + cff_charset_free_cids( CFF_Charset charset, + FT_Memory memory ) + { + FT_FREE( charset->cids ); + charset->max_cid = 0; + } + + static void cff_charset_done( CFF_Charset charset, FT_Stream stream ) { FT_Memory memory = stream->memory; + cff_charset_free_cids( charset, memory ); FT_FREE( charset->sids ); - FT_FREE( charset->cids ); charset->format = 0; charset->offset = 0; } + static FT_Error cff_charset_load( CFF_Charset charset, FT_UInt num_glyphs, @@ -1672,25 +1717,7 @@ /* we have to invert the `sids' array for subsetted CID-keyed fonts */ if ( invert ) - { - FT_UInt i; - FT_UShort max_cid = 0; - - - for ( i = 0; i < num_glyphs; i++ ) - if ( charset->sids[i] > max_cid ) - max_cid = charset->sids[i]; - max_cid++; - - if ( FT_NEW_ARRAY( charset->cids, max_cid ) ) - goto Exit; - FT_MEM_ZERO( charset->cids, sizeof ( FT_UShort ) * max_cid ); - - for ( i = 0; i < num_glyphs; i++ ) - charset->cids[charset->sids[i]] = (FT_UShort)i; - - charset->max_cid = max_cid; - } + error = cff_charset_compute_cids( charset, num_glyphs, memory ); Exit: /* Clean up if there was an error. */ @@ -1921,32 +1948,29 @@ encoding->count = 0; + error = cff_charset_compute_cids( charset, num_glyphs, stream->memory ); + if (error) + goto Exit; + for ( j = 0; j < 256; j++ ) { - /* If j is encoded, find the GID for it. */ - if ( encoding->sids[j] ) + FT_UInt sid = encoding->sids[j]; + FT_UInt gid = 0; + + if ( sid ) + gid = charset->cids[sid]; + + if ( gid != 0 ) { - for ( i = 1; i < num_glyphs; i++ ) - /* We matched, so break. */ - if ( charset->sids[i] == encoding->sids[j] ) - break; + encoding->codes[j] = (FT_UShort)gid; - /* i will be equal to num_glyphs if we exited the above */ - /* loop without a match. In this case, we also have to */ - /* fix the code to SID mapping. */ - if ( i == num_glyphs ) - { - encoding->codes[j] = 0; - encoding->sids [j] = 0; - } - else - { - encoding->codes[j] = (FT_UShort)i; - - /* update encoding count */ - if ( encoding->count < j + 1 ) - encoding->count = j + 1; - } + if ( encoding->count < j+1 ) + encoding->count = j+1; + } + else + { + encoding->codes[j] = 0; + encoding->sids [j] = 0; } } break; @@ -2013,7 +2037,7 @@ if ( error ) goto Exit; - + /* if it is a CID font, we stop there */ if ( top->cid_registry != 0xFFFFU ) goto Exit; diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c index d0140b3a1..2d4f02c1e 100644 --- a/src/sfnt/ttmtx.c +++ b/src/sfnt/ttmtx.c @@ -71,8 +71,8 @@ FT_ULong table_size; FT_Byte** ptable; FT_ULong* ptable_size; - - + + if ( vertical ) { error = face->goto_table( face, TTAG_vmtx, stream, &table_size ); @@ -91,10 +91,10 @@ ptable = &face->horz_metrics; ptable_size = &face->horz_metrics_size; } - + if ( FT_FRAME_EXTRACT( table_size, *ptable ) ) goto Fail; - + *ptable_size = table_size; Fail: @@ -116,6 +116,7 @@ TT_LongMetrics * longs; TT_ShortMetrics** shorts; + FT_Byte* p; if ( vertical ) @@ -175,6 +176,8 @@ if ( FT_FRAME_ENTER( table_len ) ) goto Fail; + p = stream->cursor; + { TT_LongMetrics cur = *longs; TT_LongMetrics limit = cur + num_longs; @@ -182,8 +185,8 @@ for ( ; cur < limit; cur++ ) { - cur->advance = FT_GET_USHORT(); - cur->bearing = FT_GET_SHORT(); + cur->advance = FT_NEXT_USHORT(p); + cur->bearing = FT_NEXT_SHORT(p); } } @@ -195,7 +198,7 @@ for ( ; cur < limit; cur++ ) - *cur = FT_GET_SHORT(); + *cur = FT_NEXT_SHORT(p); /* We fill up the missing left side bearings with the */ /* last valid value. Since this will occur for buggy CJK */ @@ -313,7 +316,7 @@ /*************************************************************************/ /* */ /* */ - /* tt_face_get_metrics */ + /* tt_face_get_metrics */ /* */ /* */ /* Returns the horizontal or vertical metrics in font units for a */