ref: 683973b47cb634dd80ac4863a556633ef1a16c03
parent: 0780817a61528391d7a85023b3c3c23ef6565729
author: David Turner <[email protected]>
date: Thu Mar 3 09:00:23 EST 2005
* 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.
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -80,6 +80,12 @@
#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 );
+
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
--- 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 */
--- 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,8 +748,8 @@
return error;
}
+#endif /* !FT_OPTIMIZE_MEMORY */
-
static const PFR_ExtraItemRec pfr_phy_font_extra_items[] =
{
{ 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },
@@ -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;
--- 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,7 @@
/*************************************************************************/
/*************************************************************************/
+#ifdef FT_OPTIMIZE_MEMORY
FT_LOCAL_DEF( FT_Error )
pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */
FT_UInt glyph1,
@@ -428,6 +432,122 @@
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,
+ 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;
PFR_KernPair pairs = phy_font->kern_pairs;
FT_UInt32 idx = PFR_KERN_INDEX( glyph1, glyph2 );
FT_UInt min, max;
@@ -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 */
--- a/src/pfr/pfrtypes.h
+++ b/src/pfr/pfrtypes.h
@@ -196,10 +196,10 @@
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 @@
#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_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;