From 4a47187b7aee8f9d44778122e1d37d9c668d8323 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 13 Mar 2012 13:18:14 +0100 Subject: [PATCH] Optimize HB memory consumption of PairPos1 in GPOS tables This is pretty much the same fix as in be0dfa34737a014e7ad060a90c4c24be9998fe13 but for PairPos format 1 instead of 2. With very simple GPOS tables we would waste a lot of memory on caching an uncompressed table, so we now compress it in memory as well. Change-Id: I601331b4b83f636dab9e1ac403b343558c15b0de Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h | 4 + src/3rdparty/harfbuzz/src/harfbuzz-gpos.c | 125 +++++++++++++++++----- 2 files changed, 101 insertions(+), 28 deletions(-) diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h b/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h index b363b81..9f0fecd 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h +++ b/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h @@ -219,8 +219,12 @@ struct HB_PairSet_ { HB_UShort PairValueCount; /* number of PairValueRecord tables */ +#ifndef HB_USE_FLEXIBLE_VALUE_RECORD HB_PairValueRecord* PairValueRecord; /* array of PairValueRecord tables */ +#else + HB_Short* ValueRecords; +#endif }; typedef struct HB_PairSet_ HB_PairSet; diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c b/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c index 8247875..217a4fd 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c @@ -185,6 +185,18 @@ HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos ) return HB_Err_Ok; } +static HB_UInt Calculate_Class2RecordSize(HB_UShort format1, HB_UShort format2) +{ + // Return number of 16 bit values in two value records with given formats + return (format1 & 0x01) + (format2 & 0x01) + + ((format1 & 0x02) >> 1) + ((format2 & 0x02) >> 1) + + ((format1 & 0x04) >> 2) + ((format2 & 0x04) >> 2) + + ((format1 & 0x08) >> 3) + ((format2 & 0x08) >> 3) + + ((format1 & 0x10) >> 4) + ((format2 & 0x10) >> 4) + + ((format1 & 0x20) >> 5) + ((format2 & 0x20) >> 5) + + ((format1 & 0x40) >> 6) + ((format2 & 0x40) >> 6) + + ((format1 & 0x80) >> 7) + ((format2 & 0x80) >> 7); +} /***************************** * SubTable related functions @@ -1096,7 +1108,6 @@ static HB_Error Lookup_SinglePos( GPOS_Instance* gpi, return HB_Err_Ok; } - /* LookupType 2 */ /* PairSet */ @@ -1111,8 +1122,12 @@ static HB_Error Load_PairSet ( HB_PairSet* ps, HB_UShort n, m, count; HB_UInt base_offset; +#ifdef HB_USE_FLEXIBLE_VALUE_RECORD + HB_UInt record_size = 0; + HB_Short *vr; +#else HB_PairValueRecord* pvr; - +#endif base_offset = FILE_Pos(); @@ -1123,6 +1138,7 @@ static HB_Error Load_PairSet ( HB_PairSet* ps, FORGET_Frame(); +#ifndef HB_USE_FLEXIBLE_VALUE_RECORD ps->PairValueRecord = NULL; if ( ALLOC_ARRAY( ps->PairValueRecord, count, HB_PairValueRecord ) ) @@ -1142,26 +1158,50 @@ static HB_Error Load_PairSet ( HB_PairSet* ps, if ( format1 ) { error = Load_ValueRecord( &pvr[n].Value1, format1, - base_offset, stream ); + base_offset, stream ); if ( error ) - goto Fail; + goto Fail; } if ( format2 ) { error = Load_ValueRecord( &pvr[n].Value2, format2, - base_offset, stream ); + base_offset, stream ); if ( error ) { - if ( format1 ) - Free_ValueRecord( &pvr[n].Value1, format1 ); - goto Fail; + if ( format1 ) + Free_ValueRecord( &pvr[n].Value1, format1 ); + goto Fail; } } } +#else + ps->ValueRecords = 0; + + // Add one for the SecondGlyph part of each record + record_size = Calculate_Class2RecordSize( format1, format2 ) + 1; + + if ( ALLOC_ARRAY( ps->ValueRecords, record_size * count, HB_Short ) ) + return error; + + vr = ps->ValueRecords; + + for ( n = 0; n < count; n++ ) + { + if ( ACCESS_Frame( 2L ) ) + goto Fail; + + for ( m = 0; m < record_size; m++ ) + *(vr++) = GET_Short(); + + FORGET_Frame(); + } +#endif + return HB_Err_Ok; Fail: +#ifndef HB_USE_FLEXIBLE_VALUE_RECORD for ( m = 0; m < n; m++ ) { if ( format1 ) @@ -1171,19 +1211,23 @@ Fail: } FREE( pvr ); +#else + FREE ( ps->ValueRecords ); +#endif + return error; } static void Free_PairSet( HB_PairSet* ps, HB_UShort format1, - HB_UShort format2 ) + HB_UShort format2) { +#ifndef HB_USE_FLEXIBLE_VALUE_RECORD HB_UShort n, count; HB_PairValueRecord* pvr; - if ( ps->PairValueRecord ) { count = ps->PairValueCount; @@ -1199,6 +1243,12 @@ static void Free_PairSet( HB_PairSet* ps, FREE( pvr ); } +#else + if ( ps->ValueRecords ) + { + FREE( ps->ValueRecords ); + } +#endif } @@ -1282,19 +1332,6 @@ static void Free_PairPos1( HB_PairPosFormat1* ppf1, } } -static HB_UInt Calculate_Class2RecordSize(HB_UShort format1, HB_UShort format2) -{ - // Return number of 16 bit values in two value records with given formats - return (format1 & 0x01) + (format2 & 0x01) - + ((format1 & 0x02) >> 1) + ((format2 & 0x02) >> 1) - + ((format1 & 0x04) >> 2) + ((format2 & 0x04) >> 2) - + ((format1 & 0x08) >> 3) + ((format2 & 0x08) >> 3) - + ((format1 & 0x10) >> 4) + ((format2 & 0x10) >> 4) - + ((format1 & 0x20) >> 5) + ((format2 & 0x20) >> 5) - + ((format1 & 0x40) >> 6) + ((format2 & 0x40) >> 6) - + ((format1 & 0x80) >> 7) + ((format2 & 0x80) >> 7); -} - /* PairPosFormat2 */ @@ -1577,7 +1614,6 @@ static void Free_PairPos( HB_GPOS_SubTable* st ) _HB_OPEN_Free_Coverage( &pp->Coverage ); } - static HB_Error Lookup_PairPos1( GPOS_Instance* gpi, HB_PairPosFormat1* ppf1, HB_Buffer buffer, @@ -1589,8 +1625,13 @@ static HB_Error Lookup_PairPos1( GPOS_Instance* gpi, HB_Error error; HB_UShort numpvr, glyph2; +#ifndef HB_USE_FLEXIBLE_VALUE_RECORD HB_PairValueRecord* pvr; - +#else + HB_Short *vr; + HB_UShort second_glyph; + HB_UInt record_size1, record_size2; +#endif if ( index >= ppf1->PairSetCount ) return ERR(HB_Err_Invalid_SubTable); @@ -1598,12 +1639,13 @@ static HB_Error Lookup_PairPos1( GPOS_Instance* gpi, if (!ppf1->PairSet[index].PairValueCount) return HB_Err_Not_Covered; + glyph2 = IN_CURGLYPH(); + +#ifndef HB_USE_FLEXIBLE_VALUE_RECORD pvr = ppf1->PairSet[index].PairValueRecord; if ( !pvr ) return ERR(HB_Err_Invalid_SubTable); - glyph2 = IN_CURGLYPH(); - for ( numpvr = ppf1->PairSet[index].PairValueCount; numpvr; numpvr--, pvr++ ) @@ -1613,11 +1655,38 @@ static HB_Error Lookup_PairPos1( GPOS_Instance* gpi, error = Get_ValueRecord( gpi, &pvr->Value1, format1, POSITION( first_pos ) ); if ( error ) - return error; + return error; return Get_ValueRecord( gpi, &pvr->Value2, format2, POSITION( buffer->in_pos ) ); } } +#else + vr = ppf1->PairSet[index].ValueRecords; + if ( !vr ) + return ERR(HB_Err_Invalid_SubTable); + + record_size1 = Calculate_Class2RecordSize( format1, 0 ); + record_size2 = Calculate_Class2RecordSize( format2, 0 ); + + for ( numpvr = ppf1->PairSet[index].PairValueCount; numpvr; numpvr-- ) + { + second_glyph = *((HB_UShort *)vr); + vr++; + if ( glyph2 == second_glyph ) + { + error = Get_FlexibleValueRecord( gpi, vr, format1, POSITION( first_pos ) ); + if ( error ) + return error; + vr += record_size1; + + return Get_FlexibleValueRecord( gpi, vr, format2, POSITION( buffer->in_pos ) ); + } + else + { + vr += record_size1 + record_size2; + } + } +#endif return HB_Err_Not_Covered; } -- 2.7.4