Optimize HB memory consumption of PairPos1 in GPOS tables
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Tue, 13 Mar 2012 12:18:14 +0000 (13:18 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 13 Mar 2012 17:06:56 +0000 (18:06 +0100)
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 <lars.knoll@nokia.com>
src/3rdparty/harfbuzz/src/harfbuzz-gpos-private.h
src/3rdparty/harfbuzz/src/harfbuzz-gpos.c

index b363b81..9f0fecd 100644 (file)
@@ -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;
index 8247875..217a4fd 100644 (file)
@@ -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;
 }