summaryrefslogtreecommitdiffstats
path: root/src/3rdparty
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2012-02-14 13:01:23 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-15 02:35:32 +0100
commitbe0dfa34737a014e7ad060a90c4c24be9998fe13 (patch)
tree16b493b12dc093410b14e431f897a0676e060b6e /src/3rdparty
parenta28c433b290dae1b3509ddf1eee616ba91ce221b (diff)
Optimize memory consumption for simple GPOS tables
Sometimes GPOS tables are used for kerning and can grow quite large if the font is unoptimized. In that case, allocating the maximum size for each ValueRecord will have a great impact on memory consumption. For GPOS tables which do not contain device tables, we only allocate the memory actually need to store the data instead. While it would be possible to optimize memory for GPOS tables that contain device tables as well, this is not a part of this patch. Change-Id: Id665b2821675ef955c497c782f09f99af765b8a3 Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Diffstat (limited to 'src/3rdparty')
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h10
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-gpos.c217
2 files changed, 170 insertions, 57 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h b/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h
index 63ba90797d..b363b81d87 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h
@@ -39,6 +39,10 @@ HB_BEGIN_HEADER
#define VR_X_ADVANCE_DEVICE 2
#define VR_Y_ADVANCE_DEVICE 3
+#ifndef HB_SUPPORT_MULTIPLE_MASTER
+# define HB_USE_FLEXIBLE_VALUE_RECORD
+#endif
+
struct HB_ValueRecord_
{
HB_Short XPlacement; /* horizontal adjustment for
@@ -242,7 +246,11 @@ typedef struct HB_Class2Record_ HB_Class2Record;
struct HB_Class1Record_
{
- HB_Class2Record* Class2Record; /* array of Class2Record tables */
+ hb_uint8 IsFlexible;
+ union {
+ HB_Class2Record* Class2Record; /* array of Class2Record tables */
+ HB_Short* ValueRecords;
+ } c2r;
};
typedef struct HB_Class1Record_ HB_Class1Record;
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c b/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c
index a21600579e..2a86cb21e9 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-gpos.c
@@ -194,6 +194,43 @@ HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos )
/* ValueRecord */
+static HB_Error Get_FlexibleValueRecord( GPOS_Instance* gpi,
+ HB_Short* vr,
+ HB_UShort format,
+ HB_Position gd )
+{
+ HB_Error error = HB_Err_Ok;
+
+ HB_16Dot16 x_scale, y_scale;
+
+ if ( !format )
+ return HB_Err_Ok;
+
+ x_scale = gpi->font->x_scale;
+ y_scale = gpi->font->y_scale;
+
+ /* design units -> fractional pixel */
+
+ if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT ) {
+ gd->x_pos += *vr * x_scale / 0x10000;
+ vr++;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT ) {
+ gd->y_pos += *vr * y_scale / 0x10000;
+ vr++;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE ) {
+ gd->x_advance += *vr * x_scale / 0x10000;
+ vr++;
+ }
+ if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE ) {
+ gd->y_advance += *vr * y_scale / 0x10000;
+ vr++;
+ }
+
+ return error;
+}
+
/* There is a subtle difference in the specs between a `table' and a
`record' -- offsets for device tables in ValueRecords are taken from
the parent table and not the parent record. */
@@ -1245,6 +1282,19 @@ 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 */
@@ -1256,11 +1306,14 @@ static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
HB_Error error;
HB_UShort m, n, k, count1, count2;
- HB_UInt cur_offset, new_offset1, new_offset2, base_offset;
+ HB_UInt cur_offset, new_offset1, new_offset2, base_offset, cls2_record_size = 0;
HB_Class1Record* c1r;
HB_Class2Record* c2r;
+ HB_Short* vr;
+
+ hb_uint8 use_flexible_value_records;
base_offset = FILE_Pos() - 8L;
@@ -1276,6 +1329,13 @@ static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
count1 = ppf2->Class1Count = GET_UShort();
count2 = ppf2->Class2Count = GET_UShort();
+#ifndef HB_USE_FLEXIBLE_VALUE_RECORD
+ use_flexible_value_records = 0;
+#else
+ use_flexible_value_records = !((format1 & HB_GPOS_FORMAT_HAVE_DEVICE_TABLES) ||
+ (format2 & HB_GPOS_FORMAT_HAVE_DEVICE_TABLES));
+#endif
+
FORGET_Frame();
cur_offset = FILE_Pos();
@@ -1296,35 +1356,55 @@ static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
c1r = ppf2->Class1Record;
+ if ( use_flexible_value_records )
+ cls2_record_size = Calculate_Class2RecordSize(format1, format2);
+
for ( m = 0; m < count1; m++ )
{
- c1r[m].Class2Record = NULL;
-
- if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) )
- goto Fail1;
-
- c2r = c1r[m].Class2Record;
-
- for ( n = 0; n < count2; n++ )
- {
- if ( format1 )
- {
- error = Load_ValueRecord( &c2r[n].Value1, format1,
- base_offset, stream );
- if ( error )
- goto Fail0;
- }
- if ( format2 )
- {
- error = Load_ValueRecord( &c2r[n].Value2, format2,
- base_offset, stream );
- if ( error )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[n].Value1, format1 );
- goto Fail0;
- }
- }
+ c1r[m].IsFlexible = use_flexible_value_records;
+ if ( use_flexible_value_records ) {
+ c1r[m].c2r.ValueRecords = NULL;
+
+ if ( ALLOC_ARRAY( c1r[m].c2r.ValueRecords, count2 * cls2_record_size, HB_UShort ) )
+ goto Fail1;
+
+ vr = c1r[m].c2r.ValueRecords;
+
+ if ( ACCESS_Frame( count2 * cls2_record_size * 2L ))
+ goto Fail1;
+
+ for ( n = 0; n < count2 * cls2_record_size; n++ )
+ vr[n] = GET_Short();
+
+ FORGET_Frame();
+ } else {
+ c1r[m].c2r.Class2Record = NULL;
+
+ if ( ALLOC_ARRAY( c1r[m].c2r.Class2Record, count2, HB_Class2Record ) )
+ goto Fail1;
+
+ c2r = c1r[m].c2r.Class2Record;
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ {
+ error = Load_ValueRecord( &c2r[n].Value1, format1,
+ base_offset, stream );
+ if ( error )
+ goto Fail0;
+ }
+ if ( format2 )
+ {
+ error = Load_ValueRecord( &c2r[n].Value2, format2,
+ base_offset, stream );
+ if ( error )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1 );
+ goto Fail0;
+ }
+ }
+ }
}
continue;
@@ -1345,17 +1425,21 @@ static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
Fail1:
for ( k = 0; k < m; k++ )
{
- c2r = c1r[k].Class2Record;
-
- for ( n = 0; n < count2; n++ )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[n].Value1, format1 );
- if ( format2 )
- Free_ValueRecord( &c2r[n].Value2, format2 );
- }
-
- FREE( c2r );
+ if ( !use_flexible_value_records ) {
+ c2r = c1r[k].c2r.Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1 );
+ if ( format2 )
+ Free_ValueRecord( &c2r[n].Value2, format2 );
+ }
+
+ FREE( c2r );
+ } else {
+ FREE( c1r[k].c2r.ValueRecords );
+ }
}
FREE( c1r );
@@ -1387,17 +1471,21 @@ static void Free_PairPos2( HB_PairPosFormat2* ppf2,
for ( m = 0; m < count1; m++ )
{
- c2r = c1r[m].Class2Record;
-
- for ( n = 0; n < count2; n++ )
- {
- if ( format1 )
- Free_ValueRecord( &c2r[n].Value1, format1 );
- if ( format2 )
- Free_ValueRecord( &c2r[n].Value2, format2 );
- }
-
- FREE( c2r );
+ if ( !c1r[m].IsFlexible ) {
+ c2r = c1r[m].c2r.Class2Record;
+
+ for ( n = 0; n < count2; n++ )
+ {
+ if ( format1 )
+ Free_ValueRecord( &c2r[n].Value1, format1 );
+ if ( format2 )
+ Free_ValueRecord( &c2r[n].Value2, format2 );
+ }
+
+ FREE( c2r );
+ } else {
+ FREE( c1r[m].c2r.ValueRecords );
+ }
}
FREE( c1r );
@@ -1544,6 +1632,10 @@ static HB_Error Lookup_PairPos2( GPOS_Instance* gpi,
HB_Class1Record* c1r;
HB_Class2Record* c2r;
+ HB_Short* vr;
+
+ HB_UShort vr1_size;
+ HB_UShort vr2_size;
error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
@@ -1558,14 +1650,27 @@ static HB_Error Lookup_PairPos2( GPOS_Instance* gpi,
c1r = &ppf2->Class1Record[cl1];
if ( !c1r )
return ERR(HB_Err_Invalid_SubTable);
- c2r = &c1r->Class2Record[cl2];
- error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
- if ( error )
- return error;
- return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
-}
+ if ( !c1r->IsFlexible ) {
+ c2r = &c1r->c2r.Class2Record[cl2];
+ error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
+ if ( error )
+ return error;
+ return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
+ } else {
+ vr1_size = Calculate_Class2RecordSize( format1, 0 );
+ vr2_size = Calculate_Class2RecordSize( format2, 0 );
+
+ vr = c1r->c2r.ValueRecords + (cl2 * ( vr1_size + vr2_size ));
+
+ error = Get_FlexibleValueRecord( gpi, vr, format1, POSITION( first_pos ) );
+ if ( error )
+ return error;
+ vr += vr1_size; // Skip to second record
+ return Get_FlexibleValueRecord( gpi, vr, format2, POSITION( buffer->in_pos ) );
+ }
+}
static HB_Error Lookup_PairPos( GPOS_Instance* gpi,
HB_GPOS_SubTable* st,