From 683973b47cb634dd80ac4863a556633ef1a16c03 Mon Sep 17 00:00:00 2001 From: David Turner Date: Thu, 3 Mar 2005 14:00:23 +0000 Subject: [PATCH] * include/freetype/internal/ftobjs.h, src/base/ftutil.c (ft_highpow2), src/pfr/pfrload.c, src/pfr/pfrobjs.c, src/pfr/pfrtypes.h: implement FT_OPTIMIZE_MEMORY, the kerning table is not loaded into the heap anymore. --- include/freetype/internal/ftobjs.h | 6 ++ src/base/ftutil.c | 20 +++++ src/pfr/pfrload.c | 8 +- src/pfr/pfrobjs.c | 136 +++++++++++++++++++++++++++-- src/pfr/pfrtypes.h | 10 ++- 5 files changed, 168 insertions(+), 12 deletions(-) diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h index 805c3aeb2..1a6130c86 100644 --- a/include/freetype/internal/ftobjs.h +++ b/include/freetype/internal/ftobjs.h @@ -80,6 +80,12 @@ FT_BEGIN_HEADER #define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 ) + /* returns the highest power of 2 that is <= value, this correspond to + * the highest bit in a given 32-bit value + */ + FT_BASE( FT_UInt32 ) + ft_highpow2( FT_UInt32 value ); + /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ diff --git a/src/base/ftutil.c b/src/base/ftutil.c index ac3760f2d..317cd95fb 100644 --- a/src/base/ftutil.c +++ b/src/base/ftutil.c @@ -398,4 +398,24 @@ } + FT_BASE( FT_UInt32 ) + ft_highpow2( FT_UInt32 value ) + { + FT_UInt32 value2; + + /* we simply clear the lowest bit in each iteration. when + * we reach 0, we now that the previous value was our result + */ + for ( ;; ) + { + value2 = value & (value-1); /* clear lowest bit */ + if ( value2 == 0 ) + break; + + value = value2; + } + return value; + } + + /* END */ diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c index 1435336b6..38a10c19d 100644 --- a/src/pfr/pfrload.c +++ b/src/pfr/pfrload.c @@ -609,6 +609,7 @@ } +#ifndef FT_OPTIMIZE_MEMORY /* * The kerning data embedded in a PFR font are (charcode,charcode) * pairs; we need to translate them to (gindex,gindex) and sort @@ -747,7 +748,7 @@ return error; } - +#endif /* !FT_OPTIMIZE_MEMORY */ static const PFR_ExtraItemRec pfr_phy_font_extra_items[] = { @@ -826,7 +827,10 @@ FT_FREE( phy_font->blue_values ); phy_font->num_blue_values = 0; +#ifndef FT_OPTIMIZE_MEMORY FT_FREE( phy_font->kern_pairs ); +#endif + { PFR_KernItem item, next; @@ -1065,8 +1069,10 @@ phy_font->bct_offset = FT_STREAM_POS(); phy_font->cursor = NULL; +#ifndef FT_OPTIMIZE_MEMORY /* now sort kerning pairs */ error = pfr_sort_kerning_pairs( stream, phy_font ); +#endif Exit: return error; diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c index 8b318e958..68e1bd944 100644 --- a/src/pfr/pfrobjs.c +++ b/src/pfr/pfrobjs.c @@ -48,7 +48,7 @@ /* we don't want dangling pointers */ pfrface->family_name = NULL; pfrface->style_name = NULL; - + /* finalize the physical font record */ pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) ); @@ -174,11 +174,11 @@ FT_Bitmap_Size* size; PFR_Strike strike; FT_Memory memory = pfrface->stream->memory; - - + + if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) ) goto Exit; - + size = pfrface->available_sizes; strike = phy_font->strikes; for ( n = 0; n < count; n++, size++, strike++ ) @@ -361,6 +361,8 @@ metrics->vertBearingX = 0; metrics->vertBearingY = 0; +#if 0 /* some fonts seem to be broken here !! */ + /* Apply the font matrix, if any. */ /* TODO: Test existing fonts with unusual matrix */ /* whether we have to adjust Units per EM. */ @@ -375,6 +377,7 @@ FT_Outline_Transform( outline, &font_matrix ); } +#endif /* scale when needed */ if ( scaling ) @@ -419,6 +422,123 @@ /*************************************************************************/ /*************************************************************************/ +#ifdef FT_OPTIMIZE_MEMORY + FT_LOCAL_DEF( FT_Error ) + pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */ + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + PFR_Face face = (PFR_Face)pfrface; + FT_Error error = PFR_Err_Ok; + PFR_PhyFont phy_font = &face->phy_font; + FT_UInt32 code1, code2, pair; + + kerning->x = 0; + kerning->y = 0; + + if ( glyph1 > 0 ) + glyph1--; + + if ( glyph2 > 0 ) + glyph2--; + + /* convert glyph indices to character codes */ + if ( glyph1 > phy_font->num_chars || + glyph2 > phy_font->num_chars ) + goto Exit; + + code1 = phy_font->chars[glyph1].char_code; + code2 = phy_font->chars[glyph2].char_code; + pair = PFR_KERN_INDEX(code1,code2); + + /* now search the list of kerning items */ + { + PFR_KernItem item = phy_font->kern_items; + FT_Stream stream = pfrface->stream; + + for ( ; item; item = item->next ) + { + if ( pair >= item->pair1 && pair <= item->pair2 ) + goto FoundPair; + } + goto Exit; + + FoundPair: /* we found an item, now parse it and find the value if any */ + if ( FT_STREAM_SEEK( item->offset ) || + FT_FRAME_ENTER( item->pair_count*item->pair_size ) ) + goto Exit; + + { + FT_UInt count = item->pair_count; + FT_UInt size = item->pair_size; + FT_UInt power = (FT_UInt)ft_highpow2( (FT_UInt32)count ); + FT_UInt probe = power*size; + FT_UInt extra = count - power; + FT_Byte* base = stream->cursor; + FT_Bool twobytes = item->flags & 1; + FT_Byte* p; + FT_UInt32 cpair; + + if ( extra > 0 ) + { + p = base + extra*size; + if ( twobytes ) + cpair = FT_NEXT_ULONG(p); + else + cpair = PFR_NEXT_KPAIR(p); + + if ( cpair == pair ) + goto Found; + + if ( cpair < pair ) + base = p; + } + + while ( probe > size ) + { + probe >>= 1; + p = base + probe; + if ( twobytes ) + cpair = FT_NEXT_ULONG(p); + else + cpair = PFR_NEXT_KPAIR(p); + + if ( cpair == pair ) + goto Found; + + if ( cpair < pair ) + base += probe; + } + + p = base; + if ( twobytes ) + cpair = FT_NEXT_ULONG(p); + else + cpair = PFR_NEXT_KPAIR(p); + + if ( cpair == pair ) + { + FT_Int value; + + Found: + if ( item->flags & 2 ) + value = FT_PEEK_SHORT(p); + else + value = p[0]; + + kerning->x = item->base_adj + value; + } + } + + FT_FRAME_EXIT(); + } + + Exit: + return error; + } + +#else /* !FT_OPTIMIZE_MEMORY */ FT_LOCAL_DEF( FT_Error ) pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */ FT_UInt glyph1, @@ -438,20 +558,20 @@ min = 0; max = phy_font->num_kern_pairs; - + while ( min < max ) { FT_UInt mid = ( min + max ) >> 1; PFR_KernPair pair = pairs + mid; FT_UInt32 pidx = PFR_KERN_PAIR_INDEX( pair ); - + if ( pidx == idx ) { kerning->x = pair->kerning; break; } - + if ( pidx < idx ) min = mid + 1; else @@ -460,6 +580,6 @@ return error; } - +#endif /* !FT_OPTIMIZE_MEMORY */ /* END */ diff --git a/src/pfr/pfrtypes.h b/src/pfr/pfrtypes.h index a10a2b26c..db593f024 100644 --- a/src/pfr/pfrtypes.h +++ b/src/pfr/pfrtypes.h @@ -196,10 +196,10 @@ FT_BEGIN_HEADER typedef struct PFR_KernItemRec_ { PFR_KernItem next; - FT_UInt pair_count; + FT_Byte pair_count; + FT_Byte flags; + FT_Short base_adj; FT_UInt pair_size; - FT_Int base_adj; - FT_UInt flags; FT_UInt32 offset; FT_UInt32 pair1; FT_UInt32 pair2; @@ -212,6 +212,8 @@ FT_BEGIN_HEADER #define PFR_KERN_PAIR_INDEX( pair ) \ PFR_KERN_INDEX( (pair)->glyph1, (pair)->glyph2 ) +#define PFR_NEXT_KPAIR(p) ( p+=2, ((FT_UInt32)p[-2] << 16) | p[-1] ) + typedef struct PFR_KernPairRec_ { FT_UInt glyph1; @@ -261,7 +263,9 @@ FT_BEGIN_HEADER FT_UInt num_kern_pairs; PFR_KernItem kern_items; PFR_KernItem* kern_items_tail; +#ifndef FT_OPTIMIZE_MEMORY PFR_KernPair kern_pairs; +#endif /* not part of the spec, but used during load */ FT_UInt32 bct_offset;